               INCLUDE HPFIXUPS
               TITLE "VINITMAIN"
***************************************************************************************************
***************************************************************************************************
***                                                                                             ***
***            VINITMAIN - BACKGROUND AND REALTIME VOICE INITIALIZATION PROCEDURES              ***
***                                                                                             ***
***************************************************************************************************
***************************************************************************************************
;
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
               INCLUDE S_BLK_EQU       ;SOUND BLOCK EQUATES/OFFSETS
;
               GLB     BKGND_NON_VEL_INIT,BKGND_VEL_INIT
               GLB     RT_NON_VEL_INIT,RT_VEL_INIT
               GLB     FULL_INIT_LIST,FULL_INIT_INDX,VEL_INIT_INDX
;
               GLB     START_VEL_BIT
               GLB     B_LEV_VEL_BIT
               GLB     B_RATE_VEL_BIT
               GLB     F_REL_VEL_BIT
               GLB     F_TIM_VEL_BIT
               GLB     F_LEV_VEL_BIT
               GLB     F_ATT_VEL_BIT
               GLB     A_REL_VEL_BIT
               GLB     A_TIM_VEL_BIT
               GLB     A_LEV_VEL_BIT
               GLB     A_ATT_VEL_BIT
               GLB     PITCH_PAN_BIT
               GLB     FIN_PITCH_BIT
               GLB     CUTOFF_BIT
;
               EXTERNAL BACK_HANDLER
               EXTERNAL VOICE_TABLE
               EXTERNAL STILL_WAITING,INIT_COMPLETE
;
               EXTERNAL  V_IDLE_SUB
               EXTERNAL  V_ACTIVE_SUB
               EXTERNAL  V_SOUND_COM
               EXTERNAL  V_SOUND_SUB
               EXTERNAL  V_NON_VEL_LIST
               EXTERNAL  V_VEL_LIST
               EXTERNAL  V_PAD_VAL_PTR
               EXTERNAL  V_PRIO_VEC
               EXTERNAL  V_PRIO_TIME
               EXTERNAL  V_VELOCITY
;
               EXTERNAL  V_INIT_START_ADDR,N_INIT_START_ADDR
               EXTERNAL  V_INIT_BEND_LEVEL,N_INIT_BEND_LEVEL
               EXTERNAL  V_INIT_BEND_RATE,N_INIT_BEND_RATE
               EXTERNAL  V_INIT_F_RELEASE,N_INIT_F_RELEASE
               EXTERNAL  V_INIT_F_TIME,N_INIT_F_TIME
               EXTERNAL  V_INIT_F_LEVEL,N_INIT_F_LEVEL
               EXTERNAL  V_INIT_F_ATTACK,N_INIT_F_ATTACK
               EXTERNAL  V_INIT_A_RELEASE,N_INIT_A_RELEASE
               EXTERNAL  V_INIT_A_TIME,N_INIT_A_TIME
               EXTERNAL  V_INIT_A_LEVEL,N_INIT_A_LEVEL
               EXTERNAL  V_INIT_A_ATTACK,N_INIT_A_ATTACK
               EXTERNAL  INIT_PITCH_PAN
               EXTERNAL  INIT_FIN_PITCH
               EXTERNAL  INIT_CUTOFF
;
               EXTERNAL  NON_VEL_INIT
               EXTERNAL  WHICH_B_VOICE
               EXTERNAL  PRIO_INDEX
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; THIS MODULE CONTAINS THE PROCEDURES FOR DOING VOICE PARAMETER INITIALIZATION IN BOTH VELOCITY-
; DEPENDENT AND NON-VELOCITY-DEPENDENT CATEGORIES, IN BOTH BACKGROUND AND REALTIME CONTEXTS.
; VINITSUBS CONTAINS THE ROUTINES INVOKED BY THESE PROCEDURES TO INITIALIZE INDIVIDUAL PARAMETERS
; OR SMALL GROUPS OF PARAMETERS - THESE ARE DESIGNED TO BE RE-ENTRANT AND EXECUTABLE FROM EITHER
; THE BACKGROUND OR REALTIME INITIALIZATION PROCEDURES (OR EVEN BOTH AT ONCE - PRETTY SLICK HUH?)
; TO ACCOMPLISH THIS, THE SUBROUTINES ARE "CALLED" VIA DIRECT BRANCH WITH "RETURN" ADDRESS IN AN
; ADDRESS REG, AND RETURN RESULTS IN DESIGNATED DATA REGS (NO DIRECT VOICE-BLOCK STORES ARE DONE BY
; VINITSUBS ROUTINES).  THEY TAKE "RETURN" VIA A BRANCH RELATIVE TO THE RETURN ADDRESS PROVIDED,
; ACCORDING TO THE SIZE OF THE RESULT BEING RETURNED - DIRECTLY IF RETURNING A WORD RESULT,
; PLUS TWO IF RETURNING A LONG-WORD RESULT, PLUS FOUR IF RETURNING A WORD BLOCK (WHICH, BY THE WAY,
; IS THE MAIN REASON FOR NOT USING SIMPLE BSR-RTS - THE OTHER REASON BEING SPEED).
;
;
FULL_INIT_LIST EQU     3FFFH           ;FOURTEEN DISCRETE VOICE SETUP ROUTINES, BIT-MAPPED.
FULL_INIT_INDX EQU     13              ;CORRESPONDING INITIALIZATION INDEX (TASKS 13 THRU 0).
VEL_INIT_INDX  EQU     10              ;ONLY TASKS 10 THRU 0 CAN EVER REQUIRE VELOCITY FOR INIT.
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; BACKGROUND NON-VELOCITY-DEPENDENT INITIALIZATION - ALL EVENTS.
;
; WE COME HERE BECAUSE ONE OR MORE BITS IS SET IN NON_VEL_INIT.
; A BIT IS CLEARED, CORRESPONDING VOICE IS INITIALIZED TO THE EXTENT INDICATED
; BY THE BITS SET IN V_NON_VEL_LIST(n) - ONE BIT PER DISCRETE PARAM INIT WITH NO VEL DEPENDENCY.
; CALLS ARE MADE TO A GROUP OF INIT SUBS WHICH ARE STREAMLINED BY OMISSION OF VEL-MOD COMPUTATIONS.
;
; ONCE DONE, V_VEL_LIST(n) IS CHECKED FOR ANY REMAINING INIT PENDING A VELOCITY VALUE -
; IF THERE IS NONE, EXIT OCCURS IMMEDIATELY - THE VOICE IS FULLY INITIALIZED.
; IF THERE IS SOME, WE LOOK TO SEE IF VEL VALUE IS PRESENT IN VOICE BLOCK (V_VELOCITY NOT = 0) -
; IF SO, VELOCITY-INIT IS BEGUN AT ONCE VIA BRANCH INTO BKGND_VEL_INIT (HAPPENS ONLY FOR MIDI AND
; SEQUENCER EVENTS, WHICH ARRIVE WITH VELOCITY BUILT IN).
; A ZERO VELOCITY VALUE IMPLIES A PAD EVENT - VELOCITY FETCH AND VEL-INIT OCCUR IN REALTIME CONTEXT
; AS PART OF THE PRIORITY SEQUENCE TO ALLOW VOICE START AT SOONEST POSSIBLE TIME AFTER PAD IS READ.
;
; IF THE TIME COMES TO PLAY THE VOICE, REALTIME MAY STEP IN AND FINISH INITIALIZATION AT ANY POINT.
; SHOULD THIS OCCUR, BACKGROUND WILL (ALMOST) IMMEDIATELY NOTICE AND MOVE ON TO SOME OTHER TASK.
;
; DEDICATED REGISTER USAGE THROUGHOUT THIS PROCEDURE AND ITS SUBORDINATE ROUTINES:
;    A0  -   "RETURN" POINTER - ALLOWS BRANCH BACK TO BACKGROUND OR REALTIME INIT PROCEDURE.
;    A1  -   VOICE COMMON BLOCK POINTER.
;    A2  -   VOICE SUB-BLOCK POINTER - IDLE SUB, SINCE PRIO SEQUENCE NOT PAST INIT_COMPLETE POINT.
;    A3  -   SOUND COMMON BLOCK POINTER.
;    A4  -   SOUND SUB-BLOCK POINTER.
;    D0  -   INITIALIZATION INDEX - WHICH PARAMETER OR PARAM GROUP IS BEING INITIALIZED.
;    D1  -   DATA RETURN REGISTER - DATA (SINGLE WORD / LONG-WORD), OR BLOCK SIZE (# WORDS - 1).
;    D2  -   ADDRESS RETURN REGISTER - INDEX INTO VOICE SUB-BLOCK FOR RESULT STORE.
; THE INDIVIDUAL INITIALIZATION ROUTINES WILL NOT FUCK AROUND WITH A0-A4
; OR D0, BUT DO FEEL FREE TO USE ANYTHING ELSE JUST AS THEY PLEASE -
; ASSUME THAT ALL REGISTERS ARE TRASHED BY THE TIME WE EXIT MAIN ROUTINE.
;
BKGND_NON_VEL_INIT
               MOVEQ   #7,D0                ;IN THE BEGINNING, WE FIND WHICH VOICE NEEDS THE HELP.
BNVI_10
               BCLR    D0,NON_VEL_INIT      ;WE CLEARS 'EM AS WE TESTS 'EM -
               DBNE    D0,BNVI_10
               BEQ     BNVI_EXIT            ;IF WE GOT HERE WITHOUT FINDING IT, IT MUST MEAN THAT
                                            ;REALTIME BEAT US TO IT - LETTUCE BEGONE.
;
               MOVE    D0,WHICH_B_VOICE     ;ELSE, MAKE A NOTE OF WHICH BE THE VOICE GETTING INIT.
               MOVE    D0,A1                ;SET A1 AS POINTER TO THE VOICE COMMON BLOCK.
               ADD     A1,A1
               MOVE    VOICE_TABLE(A1),A1
               MOVE    V_IDLE_SUB(A1),A2    ;SET A2 AS POINTER TO IDLE VOICE SUB-BLOCK.
               MOVE    V_SOUND_COM(A2),A3   ;SET A3 AS POINTER TO THE SELECTED SOUND COMMON BLOCK.
               MOVE    V_SOUND_SUB(A2),A4   ;SET A4 AS POINTER TO THE SELECTED SOUND SUB-BLOCK.
               MOVE.W  #BNVI_RETURN,A0      ;SET A0 AS "RETURN" POINTER FOR INIT ROUTINES.
               MOVE    #FULL_INIT_INDX,D0   ;SET UP TO RIP THROUGH THE FULL LIST OF INIT TASKS.
BNVI_20
               MOVE    V_NON_VEL_LIST(A1),D3     ;SEE WHO STILL NEEDS TO BE TAKEN CARE OF -
               BEQ.S   BNVI_COMPLETE             ;IF NO ONE, EITHER WE OR REALTIME FINISHED UP -
                                                 ;GO SEE ABOUT VELOCITY-DEPENDENT INITIALIZATION.
BNVI_30
               BTST    D0,D3                ;SOMEONE LEFT, FIND HIM.
               DBNE    D0,BNVI_30
;
               BRA     DO_N_INIT_TASK       ;GOT HIM - HEAD FOR NON-VEL INIT-TASK CENTRAL DISPATCH.
;
BNVI_RETURN
               BRA.S   BNVI_WORD            ;"RETURN" POINT FOR WORD RESULT.
               BRA.S   BNVI_LONG            ;"RETURN" POINT FOR LONG-WORD RESULT.
BNVI_BLOCK
                                                 ;"RETURN" POINT FOR WORD-BLOCK RESULT.
               MOVE    #2300H,SR                 ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_NON_VEL_LIST(A1),D3     ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BNVI_BLK_20               ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                     ;ELSE, SCRATCH THIS TASK OFF THE LIST.
               MOVE    D3,V_NON_VEL_LIST(A1)
               LEA     0(A2,D2),A5               ;SET UP POINTER FOR BLOCK TRANSFER OF RESULTS.
BNVI_BLK_10
               MOVE    (A7)+,(A5)+          ;YES THAT'S RIGHT - DATA BLOCK IS PASSED ON STACK!
               DBRA    D1,BNVI_BLK_10       ;D1 = (NUMBER OF WORDS TO TRANSFER - 1).
               BRA.S   BNVI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
BNVI_BLK_20
                                            ;REALTIME GOT ANTSY, FINISHED INIT FOR US -
               ADD     D1,D1                ;DISCARD RESULTS BLOCK - ADJUST STACK POINTER.
               LEA     2(A7,D1),A7
               BRA.S   BNVI_PREEMPTED       ;WE NEED NOT BOTHER CHECKING FOR VELOCITY INIT,
                                            ;"SPEEDY" IS ALREADY ON TOP OF IT ....
;
BNVI_WORD
                                                 ;"RETURN" POINT FOR SINGLE WORD RESULT.
               MOVE    #2300H,SR                 ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_NON_VEL_LIST(A1),D3     ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BNVI_PREEMPTED            ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                     ;ELSE - SCRATCH THIS TASK OFF THE LIST,
               MOVE    D3,V_NON_VEL_LIST(A1)
               MOVE    D1,0(A2,D2)               ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
               BRA.S   BNVI_TASK_DONE            ;RESULT(S) STORED - SEE WHO'S UP NEXT.
;
BNVI_LONG
                                                 ;"RETURN" POINT FOR SINGLE LONG-WORD RESULT.
               MOVE    #2300H,SR                 ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_NON_VEL_LIST(A1),D3     ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BNVI_PREEMPTED            ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                     ;ELSE - SCRATCH THIS TASK OFF THE LIST,
               MOVE    D3,V_NON_VEL_LIST(A1)
               MOVE.L  D1,0(A2,D2)               ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
;
BNVI_TASK_DONE
               MOVE    #2000H,SR            ;RESULT(S) STORED - RE-ENABLE REALTIME, ETC.
               DBRA    D0,BNVI_20           ;GO BACK FOR MORE INIT TASKS (IF ANY).
BNVI_COMPLETE
                                            ;NO MORE NON-VELOCITY-DEPENDENT INIT - WE BE CRUISIN' -
               TST     V_VEL_LIST(A1)       ;IS THERE ANY VELOCITY-DEPENDENT INITIALIZATION TO DO?
               BEQ.S   BNVI_EXIT            ;LOOKS LIKE NOT - LET'S GO EAT SUSHI... AND NOT PAY...
               TST     V_VELOCITY(A1)       ;LOOKS LIKE YES - HAVE WE GOT A VELOCITY TO PLAY WITH?
               BNE.S   BVLI_FROM_BNVI       ;YES - (THIS MUST BE A MIDI OR SEQUENCER EVENT) -
                                            ;HEAD INTO VEL INIT WITH REGISTERS ALL SET UP.
               BRA.S   BNVI_EXIT            ;NO - PAD EVENT - INIT WILL CONTINUE AFTER PAD IS READ.
;
BNVI_PREEMPTED
                                            ;REALTIME GOT ANTSY, FINISHED INIT FOR US -
               MOVE    #2000H,SR            ;RE-ENABLE REALTIME, ETC.
                                            ;WE NEED NOT BOTHER CHECKING FOR VELOCITY INIT,
                                            ;"SPEEDY" IS ALREADY ON TOP OF IT ....
BNVI_EXIT
               BRA     BACK_HANDLER         ;BACK INTO THE BACKGROUND (WHERE WE ALREADY WERE).
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; BACKGROUND VELOCITY-DEPENDENT INITIALIZATION - MIDI AND SEQUENCER EVENTS ONLY.
;
; WE COME HERE DIRECTLY FROM BKGND_NON_VEL_INIT ONCE NON-VEL INIT IS COMPLETE, WITH ALL REGISTERS
; SET UP AS SHOWN BELOW - UNLESS VOICE BEING PLAYED HAS NO VELOCITY-DEPENDENT PARAMETERS, IN WHICH
; CASE THE INIT IS COMPLETE UPON EXIT FROM BKGND_NON_VEL_INIT, SO THIS PROCEDURE IS SKIPPED.
; (NOTE:  VEL-INIT FOR PAD/TRIGGER EVENTS OCCURS FROM REALTIME VIA PRIORITY SEQUENCE, IN SYNC WITH
; READING OF VELOCITY VALUE FROM THE ASSOCIATED PAD).
;
; VOICE BLOCK INDICATED BY A1-A2 UPON ENTRY GETS ITS INITIALIZATION COMPLETED PER
; THE LIST OF BITS SET IN V_VEL_LIST(n) - ONE BIT PER DISCRETE PARAMETER INIT REQUIRING VELOCITY.
; CALLS ARE MADE TO A SEPARATE GROUP OF INIT SUBS WHICH INCORPORATE VELOCITY-MOD COMPUTATIONS.
;
; IF THE TIME COMES TO PLAY THE VOICE, REALTIME MAY STEP IN AND FINISH INITIALIZATION AT ANY POINT.
; SHOULD THIS OCCUR, BACKGROUND WILL (ALMOST) IMMEDIATELY NOTICE AND MOVE ON TO SOME OTHER TASK.
;
; DEDICATED REGISTER USAGE THROUGHOUT THIS PROCEDURE AND ITS SUBORDINATE ROUTINES:
;    A0  -   "RETURN" POINTER - ALLOWS BRANCH BACK TO BACKGROUND OR REALTIME INIT PROCEDURE.
;    A1  -   VOICE COMMON BLOCK POINTER.
;    A2  -   VOICE SUB-BLOCK POINTER - IDLE SUB, SINCE PRIO SEQUENCE NOT PAST INIT_COMPLETE POINT.
;    A3  -   SOUND COMMON BLOCK POINTER.
;    A4  -   SOUND SUB-BLOCK POINTER.
;    D0  -   INITIALIZATION INDEX - WHICH PARAMETER OR PARAM GROUP IS BEING INITIALIZED.
;    D1  -   DATA RETURN REGISTER - DATA (SINGLE WORD / LONG-WORD), OR BLOCK SIZE (# WORDS - 1).
;    D2  -   ADDRESS RETURN REGISTER - INDEX INTO VOICE SUB-BLOCK FOR RESULT STORE.
; THE INDIVIDUAL INITIALIZATION ROUTINES WILL NOT FUCK AROUND WITH A0-A4
; OR D0, BUT DO FEEL FREE TO USE ANYTHING ELSE JUST AS THEY PLEASE -
; ASSUME THAT ALL REGISTERS ARE TRASHED BY THE TIME WE EXIT MAIN ROUTINE.
;
BKGND_VEL_INIT
;
BVLI_FROM_BNVI
                                            ;ENTRY POINT IF COMING FROM BKGND_NON_VEL_INIT -
                                            ;ABOVE REGISTER SETUP IS ALREADY IN PLACE.
               MOVE.W  #BVLI_RETURN,A0      ;SET A0 AS "RETURN" POINTER FOR INIT ROUTINES.
               MOVE    #VEL_INIT_INDX,D0    ;SET UP TO RIP THROUGH THE FULL LIST OF INIT TASKS
                                            ;WHICH COULD REQUIRE A VELOCITY VALUE.
BVLI_20
               MOVE    V_VEL_LIST(A1),D3    ;SEE WHO STILL NEEDS TO BE TAKEN CARE OF -
               BEQ.S   BVLI_EXIT            ;IF NO ONE, EITHER WE OR REALTIME FINISHED VOICE INIT.
BVLI_30
               BTST    D0,D3                ;SOMEONE LEFT, FIND HIM.
               DBNE    D0,BVLI_30
;
               BRA     DO_V_INIT_TASK       ;GOT HIM - GO TO VELOCITY INIT-TASK CENTRAL DISPATCH.
;
BVLI_RETURN
               BRA.S   BVLI_WORD            ;"RETURN" POINT FOR WORD RESULT.
               BRA.S   BVLI_LONG            ;"RETURN" POINT FOR LONG-WORD RESULT.
BVLI_BLOCK
                                            ;"RETURN" POINT FOR WORD-BLOCK RESULT.
               MOVE    #2300H,SR            ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_VEL_LIST(A1),D3    ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BVLI_BLK_20          ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                ;ELSE, SCRATCH THIS TASK OFF THE LIST.
               MOVE    D3,V_VEL_LIST(A1)
               LEA     0(A2,D2),A5          ;SET UP POINTER FOR BLOCK TRANSFER OF RESULTS.
BVLI_BLK_10
               MOVE    (A7)+,(A5)+          ;YES THAT'S RIGHT - DATA BLOCK IS PASSED ON STACK!
               DBRA    D1,BVLI_BLK_10       ;D1 = (NUMBER OF WORDS TO TRANSFER - 1).
               BRA.S   BVLI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
BVLI_BLK_20
                                            ;REALTIME GOT ANTSY, FINISHED INIT FOR US -
               ADD     D1,D1                ;DISCARD RESULTS BLOCK - ADJUST STACK POINTER.
               LEA     2(A7,D1),A7
               BRA.S   BVLI_PREEMPTED       ;WE NEED NOT BOTHER CHECKING FOR VELOCITY INIT,
                                            ;"SPEEDY" IS ALREADY ON TOP OF IT ....
;
BVLI_WORD
                                            ;"RETURN" POINT FOR SINGLE WORD RESULT.
               MOVE    #2300H,SR            ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_VEL_LIST(A1),D3    ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BVLI_PREEMPTED       ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                ;ELSE - SCRATCH THIS TASK OFF THE LIST,
               MOVE    D3,V_VEL_LIST(A1)
               MOVE    D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
               BRA.S   BVLI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
;
BVLI_LONG
                                            ;"RETURN" POINT FOR SINGLE LONG-WORD RESULT.
               MOVE    #2300H,SR            ;BLOCK REALTIME WHILE RE-CHECKING INIT STATUS.
               MOVE    V_VEL_LIST(A1),D3    ;SEE IF REALTIME CAME THRU WHILE WE WERE BUSY.
               BEQ.S   BVLI_PREEMPTED       ;IF SO, WE CAN THROW THIS STUFF AWAY AND QUIT.
               BCLR    D0,D3                ;ELSE - SCRATCH THIS TASK OFF THE LIST,
               MOVE    D3,V_VEL_LIST(A1)
               MOVE.L  D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
;
BVLI_TASK_DONE
               MOVE    #2000H,SR            ;RESULT(S) STORED - RE-ENABLE REALTIME, ETC.
               DBRA    D0,BVLI_20           ;GO BACK FOR MORE INIT TASKS (IF ANY).
;
               BRA.S   BVLI_EXIT            ;NO MORE VELOCITY-DEPENDENT INIT - WE BE DONE!
;
BVLI_PREEMPTED
                                            ;REALTIME GOT ANTSY, FINISHED INIT FOR US -
               MOVE    #2000H,SR            ;RE-ENABLE REALTIME, ETC.
BVLI_EXIT
               BRA     BACK_HANDLER         ;BACK INTO THE BACKGROUND (WHERE WE ALREADY WERE).
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; REALTIME NON-VELOCITY-DEPENDENT INITIALIZATION - ALL EVENTS.
;
; WE COME HERE BECAUSE IT'S TIME TO START THE VOICE, AND THIS INITIALIZATION IS INCOMPLETE.
; VOICE(n) (n OBTAINED FROM PRIO_INDEX ON ENTRY) IS INITIALIZED ACCORDING TO THE LIST OF
; BITS SET IN V_NON_VEL_LIST(n) - ONE BIT PER DISCRETE PARAM INIT NOT REQUIRING VELOCITY.
; CALLS ARE MADE TO A GROUP OF INIT SUBS WHICH ARE STREAMLINED BY OMISSION OF VEL-MOD COMPUTATIONS.
;
; ONCE DONE, V_VEL_LIST(n) IS CHECKED FOR ANY REMAINING INIT PENDING A VELOCITY VALUE -
; IF THERE IS NONE, EXIT OCCURS IMMEDIATELY - THE VOICE IS FULLY INITIALIZED.
; IF THERE IS SOME, WE LOOK TO SEE IF VEL VALUE IS PRESENT IN VOICE BLOCK (V_VELOCITY NOT = 0) -
; IF SO, VELOCITY-INIT IS BEGUN AT ONCE VIA BRANCH INTO BKGND_VEL_INIT (HAPPENS ONLY FOR MIDI AND
; SEQUENCER EVENTS, WHICH ARRIVE WITH VELOCITY BUILT IN).
; ZERO VELOCITY IMPLIES A PAD EVENT - VOICE INIT IS SUSPENDED UNTIL REALTIME COPIES VELOCITY INTO
; VOICE BLOCK (OCCURS LATER IN SAME REALTIME, IF ASSOCIATED PAD HAS ALREADY BEEN READ).
;
; ONCE REALTIME HAS WALKED IN TO FINISH INIT, BACKGROUND WILL SEE NO FURTHER INIT REQUESTS FOR THIS
; VOICE - IT WILL (ALMOST) IMMEDIATELY NOTICE COMPLETED INIT AND MOVE ON TO SOME OTHER TASK.
;
; DEDICATED REGISTER USAGE THROUGHOUT THIS PROCEDURE AND ITS SUBORDINATE ROUTINES:
;    A0  -   "RETURN" POINTER - ALLOWS BRANCH BACK TO BACKGROUND OR REALTIME INIT PROCEDURE.
;    A1  -   VOICE COMMON BLOCK POINTER.
;    A2  -   VOICE SUB-BLOCK POINTER - IDLE SUB, SINCE PRIO SEQUENCE NOT PAST INIT_COMPLETE POINT.
;    A3  -   SOUND COMMON BLOCK POINTER.
;    A4  -   SOUND SUB-BLOCK POINTER.
;    D0  -   INITIALIZATION INDEX - WHICH PARAMETER OR PARAM GROUP IS BEING INITIALIZED.
;    D1  -   DATA RETURN REGISTER - DATA (SINGLE WORD / LONG-WORD), OR BLOCK SIZE (# WORDS - 1).
;    D2  -   ADDRESS RETURN REGISTER - INDEX INTO VOICE SUB-BLOCK FOR RESULT STORE.
; THE INDIVIDUAL INITIALIZATION ROUTINES WILL NOT FUCK AROUND WITH A0-A4
; OR D0, BUT DO FEEL FREE TO USE ANYTHING ELSE JUST AS THEY PLEASE -
; ASSUME THAT ALL REGISTERS ARE TRASHED BY THE TIME WE EXIT MAIN ROUTINE.
;
RT_NON_VEL_INIT
               MOVE    PRIO_INDEX,D0        ;FETCH INDEX OF THE VOICE GETTING INITIALIZED.
               MOVE    D0,A1                ;SET A1 AS POINTER TO THE VOICE COMMON BLOCK.
               ADD     A1,A1
               MOVE    VOICE_TABLE(A1),A1
               MOVE    V_IDLE_SUB(A1),A2    ;SET A2 AS POINTER TO IDLE VOICE SUB-BLOCK.
               MOVE    V_SOUND_COM(A2),A3   ;SET A3 AS POINTER TO THE SELECTED SOUND COMMON BLOCK.
               MOVE    V_SOUND_SUB(A2),A4   ;SET A4 AS POINTER TO THE SELECTED SOUND SUB-BLOCK.
               MOVE.W  #RNVI_RETURN,A0      ;SET A0 AS "RETURN" POINTER FOR INIT ROUTINES.
               MOVE    #FULL_INIT_INDX,D0   ;SET UP TO RIP THROUGH THE FULL LIST OF INIT TASKS.
;
               MOVE    V_NON_VEL_LIST(A1),D3     ;SEE WHO STILL NEEDS TO BE TAKEN CARE OF -
RNVI_30
               BTST    D0,D3                ;SOMEONE LEFT, FIND HIM.
               DBNE    D0,RNVI_30
;
               BRA     DO_N_INIT_TASK       ;GOT HIM - HEAD FOR NON-VEL INIT-TASK CENTRAL DISPATCH.
;
RNVI_RETURN
               BRA.S   RNVI_WORD            ;"RETURN" POINT FOR WORD RESULT.
               BRA.S   RNVI_LONG            ;"RETURN" POINT FOR LONG-WORD RESULT.
RNVI_BLOCK
                                            ;"RETURN" POINT FOR WORD-BLOCK RESULT.
               LEA     0(A2,D2),A5          ;SET UP POINTER FOR BLOCK TRANSFER OF RESULTS.
RNVI_BLK_10
               MOVE    (A7)+,(A5)+          ;YES THAT'S RIGHT - DATA BLOCK IS PASSED ON STACK!
               DBRA    D1,RNVI_BLK_10       ;D1 = (NUMBER OF WORDS TO TRANSFER - 1).
               BRA.S   RNVI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
RNVI_WORD
                                            ;"RETURN" POINT FOR SINGLE WORD RESULT.
               MOVE    D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
               BRA.S   RNVI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
;
RNVI_LONG
                                            ;"RETURN" POINT FOR SINGLE LONG-WORD RESULT.
               MOVE.L  D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
;
RNVI_TASK_DONE
               MOVE    V_NON_VEL_LIST(A1),D3     ;RESULT(S) STORED, SCRATCH THIS TASK OFF THE LIST.
               BCLR    D0,D3
               MOVE    D3,V_NON_VEL_LIST(A1)
               DBEQ    D0,RNVI_30                ;GO BACK FOR MORE INIT TASKS (IF ANY).
RNVI_COMPLETE
                                            ;NO MORE NON-VELOCITY-DEPENDENT INIT - WE BE CRUISIN' -
               TST     V_VEL_LIST(A1)       ;IS THERE ANY VELOCITY-DEPENDENT INITIALIZATION TO DO?
               BEQ     INIT_COMPLETE        ;LOOKS LIKE NOT - LET'S GO EAT SUSHI... AND NOT PAY...
                                            ;VOICE FULLY INITIALIZED, CONTINUE WITH VOICE START-UP.
               TST     V_VELOCITY(A1)       ;NEED VEL INIT - HAVE WE GOT A VELOCITY TO PLAY WITH?
               BNE.S   RVLI_FROM_RNVI       ;YES - THIS MUST BE A MIDI OR SEQUENCER EVENT -
                                            ;HEAD INTO VEL INIT WITH REGISTERS ALL SET UP.
               MOVE    V_PAD_VAL_PTR(A1),A5 ;NO - PAD EVENT - SEE IF VELOCITY HAS ALREADY BEEN READ
               MOVE    (A5),D1              ;FROM ASSOCIATED PAD.
               BEQ.S   RNVI_SUSPEND         ;ZERO VALUE MEANS NO DICE - SUSPEND INITIALIZATION.
               LSR     #3,D1                ;ELSE DO KROOD PAD-VALUE-TO-VOICE VEL TRANSFORMATION,
               BNE.S   RNVI_GOT_VEL         ;GUARD AGAINST UNWANTED ZERO RESULT,
               MOVEQ   #1,D1
RNVI_GOT_VEL
               MOVE    D1,V_VELOCITY(A1)    ;PLANT VELOCITY INTO VOICE BLOCK,
               BRA.S   RVLI_FROM_RNVI       ;GO FINISH UP THE INITIALIZATION.
;
RNVI_SUSPEND
               MOVE    #STILL_WAITING,V_PRIO_VEC(A1)  ;PAD VEL NOT YET AVAILABLE - HANG UP THIS
               MOVE    #1,V_PRIO_TIME(A1)             ;VOICE'S PRIORITY SEQUENCE AT THIS POINT,
               RTS                                    ;CHECK BACK AT NEXT REALTIME INTERVAL.
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; REALTIME VELOCITY-DEPENDENT INITIALIZATION - ALL EVENTS.
;
; WE COME HERE DIRECTLY FROM RT_NON_VEL_INIT OR FROM STILL_WAITING BECAUSE THE SOUND BEING PLAYED
; HAS ONE OR MORE VELOCITY-DEPENDENT PARAMETERS, AND ONE OF THE FOLLOWING CONDITIONS HAS OCCURED:
;    * A (PAD OR TRIG) VELOCITY VALUE WAS NEEDED FOR INITIALIZATION AND IS NOW AVAILABLE -
;    * TIME CAUGHT UP WITH A MIDI OR SEQUENCER EVENT, FORCING REALTIME TO EXPEDITE VOICE PLAY.
; IN FORMER CASE (ENTRY VIA RT_VEL_INIT), VOICE TO INITIALIZE IS INDICATED BY PRIO_INDEX -
; ELSE (ENTRY VIA RVLI_FROM_RNVI) A1-A2 ALREADY POINT AT CORRECT VOICE BLOCK.
;
; THE INDICATEDVOICE BLOCK GETS ITS INITIALIZATION COMPLETED PER
; THE LIST OF BITS SET IN V_VEL_LIST(n) - ONE BIT PER DISCRETE PARAMETER INIT REQUIRING VELOCITY.
; NOTE - WE DON'T COME HERE AT ALL IF NONE OF THESE BITS IS SET.
; CALLS ARE MADE TO A SEPARATE GROUP OF INIT SUBS WHICH INCORPORATE VELOCITY-MOD COMPUTATIONS.
;
; ONCE REALTIME HAS WALKED IN TO FINISH INIT, BACKGROUND WILL SEE NO FURTHER INIT REQUESTS FOR THIS
; VOICE - IT WILL (ALMOST) IMMEDIATELY NOTICE COMPLETED INIT AND MOVE ON TO SOME OTHER TASK.
;
; DEDICATED REGISTER USAGE THROUGHOUT THIS PROCEDURE AND ITS SUBORDINATE ROUTINES:
;    A0  -   "RETURN" POINTER - ALLOWS BRANCH BACK TO BACKGROUND OR REALTIME INIT PROCEDURE.
;    A1  -   VOICE COMMON BLOCK POINTER.
;    A2  -   VOICE SUB-BLOCK POINTER - IDLE SUB, SINCE PRIO SEQUENCE NOT PAST INIT_COMPLETE POINT.
;    A3  -   SOUND COMMON BLOCK POINTER.
;    A4  -   SOUND SUB-BLOCK POINTER.
;    D0  -   INITIALIZATION INDEX - WHICH PARAMETER OR PARAM GROUP IS BEING INITIALIZED.
;    D1  -   DATA RETURN REGISTER - DATA (SINGLE WORD / LONG-WORD), OR BLOCK SIZE (# WORDS - 1).
;    D2  -   ADDRESS RETURN REGISTER - INDEX INTO VOICE SUB-BLOCK FOR RESULT STORE.
; THE INDIVIDUAL INITIALIZATION ROUTINES WILL NOT FUCK AROUND WITH A0-A4
; OR D0, BUT DO FEEL FREE TO USE ANYTHING ELSE JUST AS THEY PLEASE -
; ASSUME THAT ALL REGISTERS ARE TRASHED BY THE TIME WE EXIT MAIN ROUTINE.
;
RT_VEL_INIT
                                            ;ENTRY POINT IF COMING FROM STILL_WAITING:
               MOVE    PRIO_INDEX,D0        ;FETCH INDEX OF THE VOICE GETTING INITIALIZED.
               MOVE    D0,A1                ;SET A1 AS POINTER TO THE VOICE COMMON BLOCK.
               ADD     A1,A1
               MOVE    VOICE_TABLE(A1),A1
               MOVE    V_IDLE_SUB(A1),A2    ;SET A2 AS POINTER TO IDLE VOICE SUB-BLOCK.
               MOVE    V_SOUND_COM(A2),A3   ;SET A3 AS POINTER TO THE SELECTED SOUND COMMON BLOCK.
               MOVE    V_SOUND_SUB(A2),A4   ;SET A4 AS POINTER TO THE SELECTED SOUND SUB-BLOCK.
RVLI_FROM_RNVI
                                            ;ENTRY POINT IF COMING FROM RT_NON_VEL_INIT -
                                            ;ABOVE REGISTER SETUP IS ALREADY IN PLACE.
               MOVE.W  #RVLI_RETURN,A0      ;SET A0 AS "RETURN" POINTER FOR INIT ROUTINES.
               MOVE    #VEL_INIT_INDX,D0    ;SET UP TO RIP THROUGH THE FULL LIST OF INIT TASKS
                                            ;WHICH COULD REQUIRE A VELOCITY VALUE.
RVLI_20
               MOVE    V_VEL_LIST(A1),D3    ;SEE WHO STILL NEEDS TO BE TAKEN CARE OF -
RVLI_30
               BTST    D0,D3                ;SOMEONE LEFT, FIND HIM.
               DBNE    D0,RVLI_30
;
               BRA     DO_V_INIT_TASK       ;GOT HIM - GO TO VELOCITY INIT-TASK CENTRAL DISPATCH.
;
RVLI_RETURN
               BRA.S   RVLI_WORD            ;"RETURN" POINT FOR WORD RESULT.
               BRA.S   RVLI_LONG            ;"RETURN" POINT FOR LONG-WORD RESULT.
RVLI_BLOCK
                                            ;"RETURN" POINT FOR WORD-BLOCK RESULT.
               LEA     0(A2,D2),A5          ;SET UP POINTER FOR BLOCK TRANSFER OF RESULTS.
RVLI_BLK_10
               MOVE    (A7)+,(A5)+          ;YES THAT'S RIGHT - DATA BLOCK IS PASSED ON STACK!
               DBRA    D1,RVLI_BLK_10       ;D1 = (NUMBER OF WORDS TO TRANSFER - 1).
               BRA.S   RVLI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
RVLI_WORD
                                            ;"RETURN" POINT FOR SINGLE WORD RESULT.
               MOVE    D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
               BRA.S   RVLI_TASK_DONE       ;RESULT(S) STORED - SEE WHO'S UP NEXT.
;
RVLI_LONG
                                            ;"RETURN" POINT FOR SINGLE LONG-WORD RESULT.
               MOVE.L  D1,0(A2,D2)          ;STORE THE RETURNED RESULT AT RETURNED LOCATION.
;
RVLI_TASK_DONE
               MOVE    V_VEL_LIST(A1),D3    ;RESULT(S) STORED, SCRATCH THIS TASK OFF THE LIST.
               BCLR    D0,D3
               MOVE    D3,V_VEL_LIST(A1)
               DBEQ    D0,RVLI_30           ;GO BACK FOR MORE INIT TASKS (IF ANY).
RVLI_EXIT
               BRA     INIT_COMPLETE        ;BACK INTO THE HIGH-PRESSURE, FAST-LANE VECTOR SCENE -
                                            ;VOICE FULLY INITIALIZED, CONTINUE WITH VOICE START-UP.
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
               SKIP
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; INTERFACE BETWEEN VOICE INITIALIZATION PROCEDURES (ABOVE) AND
; INIT ROUTINES WHICH THEY CALL (BELOW) -
; EXPECTS INITIALIZATION TASK INDEX IN D0.
; DO_N_INIT_TASK IS CALLED FOR INITIALIZATION OF PARAMETERS NOT MODIFIED
; BY EVENT VELOCITY, WHETHER INHERENTLY OR OWING TO A ZERO VEL-MOD SETTING.
; DO_V_INIT_TASK IS FOR PARAMETERS WHICH NEED VEL-MOD FOR THE CURRENT EVENT.
; DESTROYS D3, LEAVES ALL ELSE UNTOUCHED (AS IT MUST).
;
DO_N_INIT_TASK
               MOVE    D0,D3                     ;CONVERT INIT-TASK INDEX TO BRANCH TABLE OFFSET,
               ADD     D3,D3
               ADD     D3,D3
               JMP     N_INIT_TASK_TABLE(PC,D3)  ;GO BE THE TASK FOR A WHILE.
;
;
DO_V_INIT_TASK
               MOVE    D0,D3                     ;CONVERT INIT-TASK INDEX TO BRANCH TABLE OFFSET,
               ADD     D3,D3
               ADD     D3,D3
               JMP     V_INIT_TASK_TABLE(PC,D3)  ;GO BE THE TASK FOR A WHILE.
;
;
N_INIT_TASK_TABLE
                                            ;TASKS ARE ATTACKED FROM THE BOTTOM OF THE LIST.
               BRA     N_INIT_START_ADDR    ;SAMPLE PLAYBACK START ADDRESS INCLUDING VELOCITY-MOD.
               BRA     N_INIT_BEND_LEVEL    ;PITCH BEND LEVEL.
               BRA     N_INIT_BEND_RATE     ;PITCH-BEND RATE, VECTOR.
               BRA     N_INIT_F_RELEASE     ;VCF RELEASE RATE.
               BRA     N_INIT_F_TIME        ;VCF SUSTAIN TIME.
               BRA     N_INIT_F_LEVEL       ;VCF ENVELOPE LEVEL.
               BRA     N_INIT_F_ATTACK      ;VCF ATTACK RATE.
               BRA     N_INIT_A_RELEASE     ;VCA RELEASE RATE.
               BRA     N_INIT_A_TIME        ;VCA SUSTAIN TIME.
               BRA     N_INIT_A_LEVEL       ;VCA LEVEL (VOLUME).
               BRA     N_INIT_A_ATTACK      ;VCA ATTACK RATE.
                                            ;THE FOLLOWING FOUR TASKS NEVER NEED A VELOCITY VALUE.
               BRA     INIT_PITCH_PAN       ;PAN VALUE AFTER PITCH-TRACK ADJUSTMENT.
               BRA     INIT_FIN_PITCH       ;FINAL PITCH INDEX, INITIAL RAW PITCH ENVELOPE POINT.
               BRA     INIT_CUTOFF          ;NON-ENVELOPED VCF LEVEL INCLUDING PITCH-TRACK ADJUST.
;
;
V_INIT_TASK_TABLE
                                            ;TASKS ARE ATTACKED FROM THE BOTTOM OF THE LIST.
               BRA     V_INIT_START_ADDR    ;SAMPLE PLAYBACK START ADDRESS INCLUDING VELOCITY-MOD.
               BRA     V_INIT_BEND_LEVEL    ;PITCH BEND LEVEL.
               BRA     V_INIT_BEND_RATE     ;PITCH-BEND RATE, VECTOR.
               BRA     V_INIT_F_RELEASE     ;VCF RELEASE RATE.
               BRA     V_INIT_F_TIME        ;VCF SUSTAIN TIME.
               BRA     V_INIT_F_LEVEL       ;VCF ENVELOPE LEVEL.
               BRA     V_INIT_F_ATTACK      ;VCF ATTACK RATE.
               BRA     V_INIT_A_RELEASE     ;VCA RELEASE RATE.
               BRA     V_INIT_A_TIME        ;VCA SUSTAIN TIME.
               BRA     V_INIT_A_LEVEL       ;VCA LEVEL (VOLUME).
               BRA     V_INIT_A_ATTACK      ;VCA ATTACK RATE.
;
;
                                            ;BIT MASKS FOR INIT LIST.
START_VEL_BIT  EQU     0000000000000001B
B_LEV_VEL_BIT  EQU     0000000000000010B
B_RATE_VEL_BIT EQU     0000000000000100B
F_REL_VEL_BIT  EQU     0000000000001000B
F_TIM_VEL_BIT  EQU     0000000000010000B
F_LEV_VEL_BIT  EQU     0000000000100000B
F_ATT_VEL_BIT  EQU     0000000001000000B
A_REL_VEL_BIT  EQU     0000000010000000B
A_TIM_VEL_BIT  EQU     0000000100000000B
A_LEV_VEL_BIT  EQU     0000001000000000B
A_ATT_VEL_BIT  EQU     0000010000000000B
PITCH_PAN_BIT  EQU     0000100000000000B
FIN_PITCH_BIT  EQU     0001000000000000B
CUTOFF_BIT     EQU     0010000000000000B
;
;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
