fix ym2612 asm, rework EG
[picodrive.git] / pico / sound / ym2612.c
index 4b64fb4..5c52785 100644 (file)
@@ -561,7 +561,6 @@ INLINE void FM_KEYON(int c , int s )
                SLOT->key = 1;\r
                SLOT->phase = 0;                /* restart Phase Generator */\r
                SLOT->state = EG_ATT;   /* phase -> Attack */\r
-               SLOT->volume = MAX_ATT_INDEX;    /* fix Ecco 2 splash sound */\r
                ym2612.slot_mask |= (1<<s) << (c*4);\r
        }\r
 }\r
@@ -740,83 +739,57 @@ INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt)
        return lfo_ampm;\r
 }\r
 \r
-#define EG_INC_VAL() \\r
-       ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1)\r
-\r
-INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt)\r
+INLINE void update_eg_phase(UINT16 *vol_out, FM_SLOT *SLOT, UINT32 eg_cnt)\r
 {\r
        INT32 volume = SLOT->volume;\r
+       UINT32 pack = SLOT->eg_pack[SLOT->state - 1];\r
+       UINT32 shift = pack >> 24;\r
+       INT32 eg_inc_val;\r
 \r
-       switch(SLOT->state)\r
-       {\r
-               case EG_ATT:            /* attack phase */\r
-               {\r
-                       UINT32 pack = SLOT->eg_pack_ar;\r
-                       UINT32 shift = pack>>24;\r
-                       if ( !(eg_cnt & ((1<<shift)-1) ) )\r
-                       {\r
-                               volume += ( ~volume * EG_INC_VAL() ) >>4;\r
+       if (eg_cnt & ((1 << shift) - 1))\r
+               return;\r
 \r
-                               if (volume <= MIN_ATT_INDEX)\r
-                               {\r
-                                       volume = MIN_ATT_INDEX;\r
-                                       SLOT->state = EG_DEC;\r
-                               }\r
-                       }\r
-                       break;\r
-               }\r
+       eg_inc_val = pack >> ((eg_cnt >> shift) & 7) * 3;\r
+       eg_inc_val = (1 << (eg_inc_val & 7)) >> 1;\r
 \r
-               case EG_DEC:    /* decay phase */\r
+       switch (SLOT->state)\r
+       {\r
+       case EG_ATT:            /* attack phase */\r
+               volume += ( ~volume * eg_inc_val ) >> 4;\r
+               if ( volume <= MIN_ATT_INDEX )\r
                {\r
-                       UINT32 pack = SLOT->eg_pack_d1r;\r
-                       UINT32 shift = pack>>24;\r
-                       if ( !(eg_cnt & ((1<<shift)-1) ) )\r
-                       {\r
-                               volume += EG_INC_VAL();\r
-\r
-                               if ( volume >= (INT32) SLOT->sl )\r
-                                       SLOT->state = EG_SUS;\r
-                       }\r
-                       break;\r
+                       volume = MIN_ATT_INDEX;\r
+                       SLOT->state = EG_DEC;\r
                }\r
+               break;\r
 \r
-               case EG_SUS:    /* sustain phase */\r
-               {\r
-                       UINT32 pack = SLOT->eg_pack_d2r;\r
-                       UINT32 shift = pack>>24;\r
-                       if ( !(eg_cnt & ((1<<shift)-1) ) )\r
-                       {\r
-                               volume += EG_INC_VAL();\r
+       case EG_DEC:    /* decay phase */\r
+               volume += eg_inc_val;\r
+               if ( volume >= (INT32) SLOT->sl )\r
+                       SLOT->state = EG_SUS;\r
+               break;\r
 \r
-                               if ( volume >= MAX_ATT_INDEX )\r
-                               {\r
-                                       volume = MAX_ATT_INDEX;\r
-                                       /* do not change SLOT->state (verified on real chip) */\r
-                               }\r
-                       }\r
-                       break;\r
+       case EG_SUS:    /* sustain phase */\r
+               volume += eg_inc_val;\r
+               if ( volume >= MAX_ATT_INDEX )\r
+               {\r
+                       volume = MAX_ATT_INDEX;\r
+                       /* do not change SLOT->state (verified on real chip) */\r
                }\r
+               break;\r
 \r
-               case EG_REL:    /* release phase */\r
+       case EG_REL:    /* release phase */\r
+               volume += eg_inc_val;\r
+               if ( volume >= MAX_ATT_INDEX )\r
                {\r
-                       UINT32 pack = SLOT->eg_pack_rr;\r
-                       UINT32 shift = pack>>24;\r
-                       if ( !(eg_cnt & ((1<<shift)-1) ) )\r
-                       {\r
-                               volume += EG_INC_VAL();\r
-\r
-                               if ( volume >= MAX_ATT_INDEX )\r
-                               {\r
-                                       volume = MAX_ATT_INDEX;\r
-                                       SLOT->state = EG_OFF;\r
-                               }\r
-                       }\r
-                       break;\r
+                       volume = MAX_ATT_INDEX;\r
+                       SLOT->state = EG_OFF;\r
                }\r
+               break;\r
        }\r
 \r
        SLOT->volume = volume;\r
-       return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */\r
+       *vol_out = SLOT->tl + volume; /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */\r
 }\r
 #endif\r
 \r
@@ -874,10 +847,10 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
                        ct->eg_timer -= EG_TIMER_OVERFLOW;\r
                        ct->eg_cnt++;\r
 \r
-                       if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt);\r
-                       if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt);\r
-                       if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt);\r
-                       if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt);\r
+                       if (ct->CH->SLOT[SLOT1].state != EG_OFF) update_eg_phase(&ct->vol_out1, &ct->CH->SLOT[SLOT1], ct->eg_cnt);\r
+                       if (ct->CH->SLOT[SLOT2].state != EG_OFF) update_eg_phase(&ct->vol_out2, &ct->CH->SLOT[SLOT2], ct->eg_cnt);\r
+                       if (ct->CH->SLOT[SLOT3].state != EG_OFF) update_eg_phase(&ct->vol_out3, &ct->CH->SLOT[SLOT3], ct->eg_cnt);\r
+                       if (ct->CH->SLOT[SLOT4].state != EG_OFF) update_eg_phase(&ct->vol_out4, &ct->CH->SLOT[SLOT4], ct->eg_cnt);\r
                }\r
 \r
                if (ct->pack & 4) continue; /* output disabled */\r
@@ -1072,7 +1045,7 @@ static void chan_render_loop(chan_rend_context *ct, int *buffer, int length)
                        } else {\r
                                buffer[scounter] += smp;\r
                        }\r
-                       ct->algo = 8; // algo is only used in asm, here only bit3 is used\r
+                       ct->algo |= 8;\r
                }\r
 \r
                /* update phase counters AFTER output calculations */\r