YM2608/2612: applied latest fixes/discoveries [Eke-Eke, Nemesis].

This commit is contained in:
R. Belmont 2008-10-27 13:39:01 +00:00
parent db51d2ca3c
commit eb91a91308

View File

@ -7,19 +7,21 @@
** Copyright Jarek Burczynski (bujar at mame dot net)
** Copyright Tatsuyuki Satoh , MultiArcadeMachineEmulator development
**
** Version 1.4 (final beta)
** Version 1.4.2 (final beta)
**
*/
/*
** History:
**
** 2006-2008 Eke-Eke (Genesis Plus port), MAME backport by R. Belmont
** 2006-2008 Eke-Eke (Genesis Plus GX), MAME backport by R. Belmont.
** - implemented PG overflow, aka "detune bug" (Ariel, Comix Zone, Shaq Fu, Spiderman,...), credits to Nemesis
** - fixed SSG-EG support, credits to Nemesis and additional fixes from Alone Coder
** - modified EG rates and frequency, tested by Nemesis on real hardware
** - fixed EG attenuation level on KEY ON (Ecco 2 splash sound)
** - fixed LFO phase update for CH3 special mode (Warlock, Alladin), thanks to AamirM
** - implemented LFO phase update for CH3 special mode (Warlock birds, Alladin bug sound)
** - fixed Attack Rate update (Batman & Robin intro)
** - fixed attenuation level at the start of Substain (Gynoug explosions)
** - fixed EG decay->substain transition to handle special cases, like SL=0 and Decay rate is very slow (Mega Turrican tracks 03,09...)
**
** 06-23-2007 Zsolt Vasvari:
** - changed the timing not to require the use of floating point calculations
@ -701,7 +703,7 @@ typedef struct
but LFO works with one more bit of a precision so we really need 4096 elements */
UINT32 fn_table[4096]; /* fnumber->increment counter */
UINT32 fn_max; /* maximal phase increment (used for phase overflow) */
/* LFO */
UINT32 lfo_cnt;
@ -726,8 +728,6 @@ static INT32 out_delta[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM260
static UINT32 LFO_AM; /* runtime LFO calculations helper */
static INT32 LFO_PM; /* runtime LFO calculations helper */
static int fn_max; /* maximal phase increment (used for phase overflow) */
/* log output level */
#define LOG_ERR 3 /* ERROR */
#define LOG_WAR 2 /* WARNING */
@ -922,19 +922,19 @@ INLINE void FM_KEYON(UINT8 type, FM_CH *CH , int s )
{
SLOT->key = 1;
SLOT->phase = 0; /* restart Phase Generator */
SLOT->ssgn = (SLOT->ssg & 0x04) >> 1;
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
if( (SLOT->ar + SLOT->ksr) < 32+62 )
{
SLOT->state = EG_ATT; /* phase -> Attack */
SLOT->volume = MAX_ATT_INDEX; /* fix Ecco 2 splash sound */
}
else
{
/* directly switch to Decay */
SLOT->state = EG_DEC;
SLOT->volume = MIN_ATT_INDEX;
SLOT->state = EG_DEC;
}
}
else
@ -1075,6 +1075,7 @@ INLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v)
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ];
}
else
@ -1168,12 +1169,9 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm)
INLINE void advance_lfo(FM_OPN *OPN)
{
UINT8 pos;
UINT8 prev_pos;
if (OPN->lfo_inc) /* LFO enabled ? */
{
prev_pos = OPN->lfo_cnt>>LFO_SH & 127;
OPN->lfo_cnt += OPN->lfo_inc;
pos = (OPN->lfo_cnt >> LFO_SH) & 127;
@ -1181,7 +1179,6 @@ INLINE void advance_lfo(FM_OPN *OPN)
/* update AM when LFO output changes */
/*if (prev_pos != pos)*/
/* actually I can't optimize is this way without rewritting chan_calc()
to use chip->lfo_am instead of global lfo_am */
{
@ -1195,7 +1192,6 @@ INLINE void advance_lfo(FM_OPN *OPN)
}
/* PM works with 4 times slower clock */
prev_pos >>= 2;
pos >>= 2;
/* update PM when LFO output changes */
/*if (prev_pos != pos)*/ /* can't use global lfo_pm for this optimization, must be chip->lfo_pm instead*/
@ -1222,6 +1218,9 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
i = 4; /* four operators per channel */
do
{
/* reset SSG-EG swap flag */
swap_flag = 0;
switch(SLOT->state)
{
case EG_ATT: /* attack phase */
@ -1240,24 +1239,48 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
break;
case EG_DEC: /* decay phase */
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
{
SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
{
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
{
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
}
else
{
SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
}
}
if ( SLOT->volume >= (INT32)(SLOT->sl) )
SLOT->state = EG_SUS;
/* check transition even if no volume update: this fixes the case when SL = MIN_ATT_INDEX */
if ( SLOT->volume >= (INT32)(SLOT->sl) )
{
SLOT->volume = (INT32)(SLOT->sl);
SLOT->state = EG_SUS;
}
}
else
{
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
{
SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
{
SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
if ( SLOT->volume >= (INT32)(SLOT->sl) )
SLOT->state = EG_SUS;
if ( SLOT->volume >= (INT32)(SLOT->sl) )
SLOT->state = EG_SUS;
}
}
else
{
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
{
SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
if ( SLOT->volume >= (INT32)(SLOT->sl) )
SLOT->state = EG_SUS;
}
}
}
break;
@ -1267,11 +1290,22 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
{
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) )
{
SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];
if ( SLOT->volume >= 512 )
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->volume = MAX_ATT_INDEX;
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];
}
else
{
SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];
}
if ( SLOT->volume >= ENV_QUIET )
{
if ((OPN->type != TYPE_YM2612) && (OPN->type != TYPE_YM2608))
{
SLOT->volume = MAX_ATT_INDEX;
}
if (SLOT->ssg&0x01) /* bit 0 = hold */
{
@ -1287,13 +1321,28 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
{
/* same as KEY-ON operation */
/* restart of the Phase Generator should be here,
only if AR is not maximum ??? */
/* restart of the Phase Generator should be here */
SLOT->phase = 0;
/* phase -> Attack */
SLOT->volume = 511;
SLOT->state = EG_ATT;
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)
{
SLOT->state = EG_ATT; /* phase -> Attack */
}
else
{
/* Attack Rate is maximal: directly switch to Decay (or Substain) */
SLOT->volume = MIN_ATT_INDEX;
SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;
}
}
else
{
/* phase -> Attack */
SLOT->volume = 511;
SLOT->state = EG_ATT;
}
swap_flag = (SLOT->ssg&0x02); /* bit 1 = alternate */
}
@ -1319,7 +1368,15 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
case EG_REL: /* release phase */
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_rr)-1) ) )
{
SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];
/* SSG-EG affects Release phase also (Nemesis) */
if ((SLOT->ssg&0x08) && ((OPN->type = TYPE_YM2612) || (OPN->type = TYPE_YM2608)))
{
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];
}
else
{
SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];
}
if ( SLOT->volume >= MAX_ATT_INDEX )
{
@ -1331,15 +1388,18 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
}
out = SLOT->tl + ((UINT32)SLOT->volume);
if ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state != EG_OFF)) /* negate output (changes come from alternate bit, init comes from attack bit) */
out ^= 511; // was ((1<<ENV_BITS)-1); /* 1023 */
out = ((UINT32)SLOT->volume);
/* negate output (changes come from alternate bit, init comes from attack bit) */
if ((SLOT->ssg&0x08) && (SLOT->ssgn&2) && (SLOT->state > EG_REL))
out ^= MAX_ATT_INDEX;
/* we need to store the result here because we are going to change ssgn
in next instruction */
SLOT->vol_out = out;
SLOT->vol_out = out + SLOT->tl;
/* reverse SLOT inversion flag */
SLOT->ssgn ^= swap_flag;
SLOT++;
@ -1375,7 +1435,7 @@ INLINE void update_phase_lfo_slot(FM_OPN *OPN, FM_SLOT *SLOT, INT32 pms, UINT32
fc = (OPN->fn_table[fn]>>(7-blk)) + SLOT->DT[kc];
/* detects frequency overflow (credits to Nemesis) */
if (fc < 0) fc += fn_max;
if (fc < 0) fc += OPN->fn_max;
/* update phase */
SLOT->phase += (fc * SLOT->mul) >> 1;
@ -1413,19 +1473,19 @@ INLINE void update_phase_lfo_channel(FM_OPN *OPN, FM_CH *CH)
/* detects frequency overflow (credits to Nemesis) */
finc = fc + CH->SLOT[SLOT1].DT[kc];
if (finc < 0) finc += fn_max;
if (finc < 0) finc += OPN->fn_max;
CH->SLOT[SLOT1].phase += (finc*CH->SLOT[SLOT1].mul) >> 1;
finc = fc + CH->SLOT[SLOT2].DT[kc];
if (finc < 0) finc += fn_max;
if (finc < 0) finc += OPN->fn_max;
CH->SLOT[SLOT2].phase += (finc*CH->SLOT[SLOT2].mul) >> 1;
finc = fc + CH->SLOT[SLOT3].DT[kc];
if (finc < 0) finc += fn_max;
if (finc < 0) finc += OPN->fn_max;
CH->SLOT[SLOT3].phase += (finc*CH->SLOT[SLOT3].mul) >> 1;
finc = fc + CH->SLOT[SLOT4].DT[kc];
if (finc < 0) finc += fn_max;
if (finc < 0) finc += OPN->fn_max;
CH->SLOT[SLOT4].phase += (finc*CH->SLOT[SLOT4].mul) >> 1;
}
else /* LFO phase modulation = zero */
@ -1512,14 +1572,14 @@ INLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum)
}
/* update phase increment and envelope generator */
INLINE void refresh_fc_eg_slot(UINT8 type, FM_SLOT *SLOT , int fc , int kc )
INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )
{
int ksr = kc >> SLOT->KSR;
fc += SLOT->DT[kc];
/* detects frequency overflow (credits to Nemesis) */
if (fc < 0) fc += fn_max;
if (fc < 0) fc += OPN->fn_max;
/* (frequency) phase increment counter */
SLOT->Incr = (fc * SLOT->mul) >> 1;
@ -1532,7 +1592,7 @@ INLINE void refresh_fc_eg_slot(UINT8 type, FM_SLOT *SLOT , int fc , int kc )
if ((SLOT->ar + SLOT->ksr) < 32+62)
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ];
}
@ -1551,7 +1611,7 @@ INLINE void refresh_fc_eg_slot(UINT8 type, FM_SLOT *SLOT , int fc , int kc )
SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr];
SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr];
@ -1568,15 +1628,15 @@ INLINE void refresh_fc_eg_slot(UINT8 type, FM_SLOT *SLOT , int fc , int kc )
/* update phase increment counters */
/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */
static void refresh_fc_eg_chan(UINT8 type, FM_CH *CH )
static void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH )
{
if( CH->SLOT[SLOT1].Incr==-1){
int fc = CH->fc;
int kc = CH->kcode;
refresh_fc_eg_slot(type, &CH->SLOT[SLOT1] , fc , kc );
refresh_fc_eg_slot(type, &CH->SLOT[SLOT2] , fc , kc );
refresh_fc_eg_slot(type, &CH->SLOT[SLOT3] , fc , kc );
refresh_fc_eg_slot(type, &CH->SLOT[SLOT4] , fc , kc );
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc );
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT2] , fc , kc );
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT3] , fc , kc );
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT4] , fc , kc );
}
}
@ -1761,13 +1821,27 @@ static void FMCloseTable( void )
/* CSM Key Controll */
INLINE void CSMKeyControll(UINT8 type, FM_CH *CH)
{
/* this is wrong, atm */
/* all key on */
FM_KEYON(type, CH,SLOT1);
FM_KEYON(type, CH,SLOT2);
FM_KEYON(type, CH,SLOT3);
FM_KEYON(type, CH,SLOT4);
/* all key on then off (only for operators which were OFF!) */
if (!CH->SLOT[SLOT1].key)
{
FM_KEYON(type, CH,SLOT1);
FM_KEYOFF(CH, SLOT1);
}
if (!CH->SLOT[SLOT2].key)
{
FM_KEYON(type, CH,SLOT2);
FM_KEYOFF(CH, SLOT2);
}
if (!CH->SLOT[SLOT3].key)
{
FM_KEYON(type, CH,SLOT3);
FM_KEYOFF(CH, SLOT3);
}
if (!CH->SLOT[SLOT4].key)
{
FM_KEYON(type, CH,SLOT4);
FM_KEYOFF(CH, SLOT4);
}
}
#ifdef __STATE_H__
@ -1861,9 +1935,9 @@ static void OPNSetPres(FM_OPN *OPN, int pres, int timer_prescaler, int SSGpres)
#endif
}
/* maximal frequency, used for overflow, best setting with BLOCK=5 (notaz) */
fn_max = ((UINT32)((double)OPN->fn_table[0x7ff*2] / OPN->ST.freqbase) >> 2);
/* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */
OPN->fn_max = (UINT32)( (double)0x20000 * OPN->ST.freqbase * (1<<(FREQ_SH-10)) );
/* LFO freq. table */
for(i = 0; i < 8; i++)
{
@ -2204,19 +2278,19 @@ void ym2203_update_one(void *chip, FMSAMPLE *buffer, int length)
/* refresh PG and EG */
refresh_fc_eg_chan( OPN->type, cch[0] );
refresh_fc_eg_chan( OPN->type, cch[1] );
refresh_fc_eg_chan( OPN, cch[0] );
refresh_fc_eg_chan( OPN, cch[1] );
if( (F2203->OPN.ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else refresh_fc_eg_chan( OPN->type, cch[2] );
}else refresh_fc_eg_chan( OPN, cch[2] );
/* YM2203 doesn't have LFO so we must keep these globals at 0 level */
@ -3386,22 +3460,22 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
pcmsizeA = F2608->pcm_size;
/* refresh PG and EG */
refresh_fc_eg_chan( OPN->type, cch[0] );
refresh_fc_eg_chan( OPN->type, cch[1] );
refresh_fc_eg_chan( OPN, cch[0] );
refresh_fc_eg_chan( OPN, cch[1] );
if( (OPN->ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else refresh_fc_eg_chan( OPN->type, cch[2] );
refresh_fc_eg_chan( OPN->type, cch[3] );
refresh_fc_eg_chan( OPN->type, cch[4] );
refresh_fc_eg_chan( OPN->type, cch[5] );
}else refresh_fc_eg_chan( OPN, cch[2] );
refresh_fc_eg_chan( OPN, cch[3] );
refresh_fc_eg_chan( OPN, cch[4] );
refresh_fc_eg_chan( OPN, cch[5] );
/* buffering */
@ -3421,21 +3495,6 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
out_fm[4] = 0;
out_fm[5] = 0;
/* advance envelope generator */
OPN->eg_timer += OPN->eg_timer_add;
while (OPN->eg_timer >= OPN->eg_timer_overflow)
{
OPN->eg_timer -= OPN->eg_timer_overflow;
OPN->eg_cnt++;
advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);
}
/* calculate FM */
chan_calc(OPN, cch[0], 0 );
chan_calc(OPN, cch[1], 1 );
@ -3455,6 +3514,21 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
ADPCMA_calc_chan( F2608, &F2608->adpcm[j]);
}
/* advance envelope generator */
OPN->eg_timer += OPN->eg_timer_add;
while (OPN->eg_timer >= OPN->eg_timer_overflow)
{
OPN->eg_timer -= OPN->eg_timer_overflow;
OPN->eg_cnt++;
advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);
}
/* buffering */
{
int lt,rt;
@ -3940,20 +4014,20 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
#endif
/* refresh PG and EG */
refresh_fc_eg_chan( OPN->type, cch[0] );
refresh_fc_eg_chan( OPN, cch[0] );
if( (OPN->ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[1]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN->type, &cch[1]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN->type, &cch[1]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN->type, &cch[1]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN->type, &cch[1]->SLOT[SLOT4] , cch[1]->fc , cch[1]->kcode );
refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[1]->SLOT[SLOT4] , cch[1]->fc , cch[1]->kcode );
}
}else refresh_fc_eg_chan( OPN->type, cch[1] );
refresh_fc_eg_chan( OPN->type, cch[2] );
refresh_fc_eg_chan( OPN->type, cch[3] );
}else refresh_fc_eg_chan( OPN, cch[1] );
refresh_fc_eg_chan( OPN, cch[2] );
refresh_fc_eg_chan( OPN, cch[3] );
/* buffering */
for(i=0; i < length ; i++)
@ -4069,22 +4143,22 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
pcmsizeA = F2610->pcm_size;
/* refresh PG and EG */
refresh_fc_eg_chan( OPN->type, cch[0] );
refresh_fc_eg_chan( OPN->type, cch[1] );
refresh_fc_eg_chan( OPN, cch[0] );
refresh_fc_eg_chan( OPN, cch[1] );
if( (OPN->ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else refresh_fc_eg_chan( OPN->type, cch[2] );
refresh_fc_eg_chan( OPN->type, cch[3] );
refresh_fc_eg_chan( OPN->type, cch[4] );
refresh_fc_eg_chan( OPN->type, cch[5] );
}else refresh_fc_eg_chan( OPN, cch[2] );
refresh_fc_eg_chan( OPN, cch[3] );
refresh_fc_eg_chan( OPN, cch[4] );
refresh_fc_eg_chan( OPN, cch[5] );
/* buffering */
for(i=0; i < length ; i++)
@ -4590,22 +4664,22 @@ void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
dacen = F2612->dacen;
/* refresh PG and EG */
refresh_fc_eg_chan( OPN->type, cch[0] );
refresh_fc_eg_chan( OPN->type, cch[1] );
refresh_fc_eg_chan( OPN, cch[0] );
refresh_fc_eg_chan( OPN, cch[1] );
if( (OPN->ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN->type, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else refresh_fc_eg_chan( OPN->type, cch[2] );
refresh_fc_eg_chan( OPN->type, cch[3] );
refresh_fc_eg_chan( OPN->type, cch[4] );
refresh_fc_eg_chan( OPN->type, cch[5] );
}else refresh_fc_eg_chan( OPN, cch[2] );
refresh_fc_eg_chan( OPN, cch[3] );
refresh_fc_eg_chan( OPN, cch[4] );
refresh_fc_eg_chan( OPN, cch[5] );
/* buffering */
for(i=0; i < length ; i++)
@ -4621,6 +4695,17 @@ void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
out_fm[4] = 0;
out_fm[5] = 0;
/* calculate FM */
chan_calc(OPN, cch[0], 0 );
chan_calc(OPN, cch[1], 1 );
chan_calc(OPN, cch[2], 2 );
chan_calc(OPN, cch[3], 3 );
chan_calc(OPN, cch[4], 4 );
if( dacen )
*cch[5]->connect4 += dacout;
else
chan_calc(OPN, cch[5], 5 );
/* advance envelope generator */
OPN->eg_timer += OPN->eg_timer_add;
while (OPN->eg_timer >= OPN->eg_timer_overflow)
@ -4636,17 +4721,6 @@ void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);
}
/* calculate FM */
chan_calc(OPN, cch[0], 0 );
chan_calc(OPN, cch[1], 1 );
chan_calc(OPN, cch[2], 2 );
chan_calc(OPN, cch[3], 3 );
chan_calc(OPN, cch[4], 4 );
if( dacen )
*cch[5]->connect4 += dacout;
else
chan_calc(OPN, cch[5], 5 );
{
int lt,rt;