small fix to SSG-EG emulation

This commit is contained in:
ekeeke31 2009-02-27 09:09:06 +00:00
parent a857fb3990
commit 914b8d22f2

View File

@ -563,7 +563,7 @@ typedef struct
UINT8 fn_h; /* freq3 latch */ UINT8 fn_h; /* freq3 latch */
UINT8 kcode[3]; /* key code */ UINT8 kcode[3]; /* key code */
UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */
UINT8 key_csm; /* 1: KEY ON event occured in CSM mode */ UINT8 key_csm; /* CSM mode Key-ON flag */
} FM_3SLOT; } FM_3SLOT;
@ -622,7 +622,7 @@ INLINE void FM_KEYON(FM_CH *CH , int s )
{ {
FM_SLOT *SLOT = &CH->SLOT[s]; FM_SLOT *SLOT = &CH->SLOT[s];
if( !SLOT->key && !ym2612.OPN.SL3.key_csm) if (!SLOT->key && !ym2612.OPN.SL3.key_csm)
{ {
/* restart Phase Generator */ /* restart Phase Generator */
SLOT->phase = 0; SLOT->phase = 0;
@ -657,17 +657,27 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
{ {
FM_SLOT *SLOT = &CH->SLOT[s]; FM_SLOT *SLOT = &CH->SLOT[s];
if( SLOT->key && !ym2612.OPN.SL3.key_csm) if (SLOT->key && !ym2612.OPN.SL3.key_csm)
{ {
if (SLOT->state>EG_REL) if (SLOT->state>EG_REL)
{ {
SLOT->state = EG_REL; /* phase -> Release */ SLOT->state = EG_REL; /* phase -> Release */
/* SSG-EG */ /* SSG-EG specific update */
if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) if (SLOT->ssg&0x08)
{ {
/* recalculate proper volume */ /* convert EG attenuation level */
SLOT->volume = ((UINT32)SLOT->volume ^ 0x1FF) + 1; /* Invert Attenuation */ if (SLOT->ssgn ^ (SLOT->ssg&0x04))
SLOT->volume = ((UINT32)SLOT->volume ^ 0x1FF) + 1;
/* force EG attenuation level */
if (SLOT->volume >= 0x200)
{
SLOT->volume = MAX_ATT_INDEX;
SLOT->state = EG_OFF;
}
/* recalculate EG output */
SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;
} }
} }
@ -680,7 +690,7 @@ INLINE void FM_KEYON_CSM(FM_CH *CH , int s )
{ {
FM_SLOT *SLOT = &CH->SLOT[s]; FM_SLOT *SLOT = &CH->SLOT[s];
if( !SLOT->key && !ym2612.OPN.SL3.key_csm) if (!SLOT->key && !ym2612.OPN.SL3.key_csm)
{ {
/* restart Phase Generator */ /* restart Phase Generator */
SLOT->phase = 0; SLOT->phase = 0;
@ -712,17 +722,27 @@ INLINE void FM_KEYON_CSM(FM_CH *CH , int s )
INLINE void FM_KEYOFF_CSM(FM_CH *CH , int s ) INLINE void FM_KEYOFF_CSM(FM_CH *CH , int s )
{ {
FM_SLOT *SLOT = &CH->SLOT[s]; FM_SLOT *SLOT = &CH->SLOT[s];
if( !SLOT->key ) if (!SLOT->key)
{ {
if (SLOT->state>EG_REL) if (SLOT->state>EG_REL)
{ {
SLOT->state = EG_REL; /* phase -> Release */ SLOT->state = EG_REL; /* phase -> Release */
/* SSG-EG */ /* SSG-EG specific update */
if ((SLOT->ssg&0x08) && (SLOT->ssgn ^ (SLOT->ssg&0x04))) if (SLOT->ssg&0x08)
{ {
/* recalculate proper volume */ /* convert EG attenuation level */
SLOT->volume = ((UINT32)SLOT->volume ^ 0x1FF) + 1; /* Invert Attenuation */ if (SLOT->ssgn ^ (SLOT->ssg&0x04))
SLOT->volume = ((UINT32)SLOT->volume ^ 0x1FF) + 1;
/* force EG attenuation level */
if (SLOT->volume >= 0x200)
{
SLOT->volume = MAX_ATT_INDEX;
SLOT->state = EG_OFF;
}
/* recalculate EG output */
SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl; SLOT->vol_out = (UINT32)SLOT->volume + SLOT->tl;
} }
} }
@ -1153,14 +1173,14 @@ INLINE void update_ssg_eg_channel(FM_SLOT *SLOT)
do do
{ {
/* detect SSG-EG transition */ /* detect SSG-EG transition */
/* this is not required during release phase as the attenuation is set to MAX and output invert flag is not used */ /* this is not required during release phase as the attenuation has been forced to MAX and output invert flag is not used */
/* if an Attack Phase is programmed, inversion can occur on each sample */ /* if an Attack Phase is programmed, inversion can occur on each sample */
if ((SLOT->ssg & 0x08) && (SLOT->volume >= 0x200) && (SLOT->state > EG_REL)) if ((SLOT->ssg & 0x08) && (SLOT->volume >= 0x200) && (SLOT->state > EG_REL))
{ {
if (SLOT->ssg & 0x01) /* bit 0 = hold SSG-EG */ if (SLOT->ssg & 0x01) /* bit 0 = hold SSG-EG */
{ {
/* set inversion flag */ /* force inversion flag */
if ((SLOT->ssg & 0x02) && !SLOT->ssgn) if (SLOT->ssg & 0x02)
SLOT->ssgn = 4; SLOT->ssgn = 4;
/* force attenuation level */ /* force attenuation level */
@ -1170,8 +1190,10 @@ INLINE void update_ssg_eg_channel(FM_SLOT *SLOT)
else /* loop SSG-EG */ else /* loop SSG-EG */
{ {
/* toggle output inversion flag or reset Phase Generator */ /* toggle output inversion flag or reset Phase Generator */
if (SLOT->ssg & 0x02) SLOT->ssgn ^= 4; if (SLOT->ssg & 0x02)
else SLOT->phase = 0; SLOT->ssgn ^= 4;
else
SLOT->phase = 0;
/* same as Key ON */ /* same as Key ON */
if (SLOT->state != EG_ATT) if (SLOT->state != EG_ATT)