mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 11:41:48 +01:00
+fixed LFO implementation according to Nemesis description (UNTESTED, need feedback)
This commit is contained in:
parent
256d534ea6
commit
0c8c30e3a2
@ -14,12 +14,13 @@
|
||||
**
|
||||
** 2006~2009 Eke-Eke (Genesis Plus GX):
|
||||
** Credits to Nemesis (@spritesmind.net), most of those fixes came from his tests on a Model 1 Sega Mega Drive
|
||||
** More informations here: http://gendev.spritesmind.net/forum/viewtopic.php?t=386
|
||||
**
|
||||
** - removed unused multichip support
|
||||
** - added YM2612 Context external access functions
|
||||
** - added LFO phase update in CH3 special mode (Warlock birds, Alladin bug sound)
|
||||
** - fixed internal timers emulation
|
||||
** - added Attack Rate immediate update on register write (Batman & Robin intro)
|
||||
** - implemented LFO phase update in CH3 special mode (Warlock birds, Alladin bug sound)
|
||||
** - improved internal timers emulation
|
||||
** - fixed Attack Rate update in some specific case (Batman & Robin intro)
|
||||
** - fixed EG behavior when Attack Rate is maximal
|
||||
** - fixed EG behavior when SL=0 (Mega Turrican tracks 03,09...) or/and Key ON occurs at minimal attenuation
|
||||
** - added EG output immediate update on register writes
|
||||
@ -29,6 +30,7 @@
|
||||
** - implemented correct SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Six & many others)
|
||||
** - adjusted some EG rates
|
||||
** - modified address/data port behavior
|
||||
** - fixed LFO implementation (only 11 bits of precision)
|
||||
**
|
||||
** TODO: complete SSG-EG documentation
|
||||
**
|
||||
@ -582,9 +584,8 @@ typedef struct
|
||||
UINT32 eg_timer_add; /* step of eg_timer */
|
||||
UINT32 eg_timer_overflow; /* envelope generator timer overlfows every 3 samples (on real chip) */
|
||||
|
||||
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers
|
||||
but LFO works with one more bit of a precision so we really need 4096 elements */
|
||||
UINT32 fn_table[4096]; /* fnumber->increment counter */
|
||||
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers */
|
||||
UINT32 fn_table[2048]; /* fnumber->increment counter */
|
||||
UINT32 fn_max; /* max increment (required for calculating phase overflow) */
|
||||
|
||||
/* LFO */
|
||||
@ -1237,20 +1238,21 @@ INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum)
|
||||
{
|
||||
UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
|
||||
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + LFO_PM ];
|
||||
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
|
||||
/* retrieve BLOCK register value */
|
||||
UINT8 blk = (block_fnum >> 11) & 7;
|
||||
|
||||
UINT8 blk = (block_fnum&0x7000) >> 12;
|
||||
UINT32 fn = block_fnum & 0xfff;
|
||||
/* increase FNUM register value */
|
||||
UINT32 fn = (block_fnum + lfo_fn_table_index_offset) & 0x7ff;
|
||||
|
||||
/* keyscale code */
|
||||
int kc = (blk<<2) | opn_fktable[fn >> 8];
|
||||
/* recalculate keyscale code */
|
||||
int kc = (blk<<2) | opn_fktable[fn >> 7];
|
||||
|
||||
/* (frequency) phase increment counter */
|
||||
/* recalculate (frequency) phase increment counter */
|
||||
int fc = (ym2612.OPN.fn_table[fn]>>(7-blk)) + SLOT->DT[kc];
|
||||
|
||||
|
||||
/* (frequency) phase overflow (credits to Nemesis) */
|
||||
if (fc < 0) fc += ym2612.OPN.fn_max;
|
||||
|
||||
@ -1266,21 +1268,22 @@ INLINE void update_phase_lfo_slot(FM_SLOT *SLOT , INT32 pms, UINT32 block_fnum)
|
||||
INLINE void update_phase_lfo_channel(FM_CH *CH)
|
||||
{
|
||||
UINT32 block_fnum = CH->block_fnum;
|
||||
|
||||
|
||||
UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8;
|
||||
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + LFO_PM ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
block_fnum = block_fnum*2 + lfo_fn_table_index_offset;
|
||||
/* retrieve BLOCK register value */
|
||||
UINT8 blk = (block_fnum >> 11) & 7;
|
||||
|
||||
UINT8 blk = (block_fnum&0x7000) >> 12;
|
||||
UINT32 fn = block_fnum & 0xfff;
|
||||
|
||||
/* keyscale code */
|
||||
int kc = (blk<<2) | opn_fktable[fn >> 8];
|
||||
/* increase FNUM register value */
|
||||
UINT32 fn = (block_fnum + lfo_fn_table_index_offset)& 0x7ff;
|
||||
|
||||
/* (frequency) phase increment counter */
|
||||
/* recalculate keyscale code */
|
||||
int kc = (blk<<2) | opn_fktable[fn >> 7];
|
||||
|
||||
/* recalculate (frequency) phase increment counter */
|
||||
int fc = (ym2612.OPN.fn_table[fn]>>(7-blk));
|
||||
|
||||
/* (frequency) phase overflow (credits to Nemesis) */
|
||||
@ -1316,7 +1319,6 @@ INLINE void chan_calc(FM_CH *CH)
|
||||
|
||||
UINT32 AM = LFO_AM >> CH->ams;
|
||||
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
|
||||
*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
@ -1356,7 +1358,6 @@ INLINE void chan_calc(FM_CH *CH)
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 4 */
|
||||
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);
|
||||
|
||||
|
||||
/* store current MEM */
|
||||
CH->mem_value = mem;
|
||||
|
||||
@ -1631,14 +1632,17 @@ static void OPNSetPres(int pres)
|
||||
/* make time tables */
|
||||
init_timetables(dt_tab);
|
||||
|
||||
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers
|
||||
but LFO works with one more bit of a precision so we really need 4096 elements */
|
||||
/* there are 2048 FNUMs that can be generated using FNUM/BLK registers */
|
||||
/* calculate fnumber -> increment counter table */
|
||||
for(i = 0; i < 4096; i++)
|
||||
for(i = 0; i < 2048; i++)
|
||||
{
|
||||
/* freq table for octave 7 */
|
||||
/* OPN phase increment counter = 20bit */
|
||||
ym2612.OPN.fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
|
||||
/* the correct formula is : F-Number = (144 * fnote * 2^20 / M) / 2^(B-1) */
|
||||
/* where sample clock is M/144 */
|
||||
/* this means the increment value for one clock sample is FNUM * 2^(B-1) = FNUM * 64 for octave 7 */
|
||||
/* we also need to handle the ratio between the chip frequency and the emulated frequency (can be 1.0) */
|
||||
ym2612.OPN.fn_table[i] = (UINT32)( (double)i * 64 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
|
||||
}
|
||||
|
||||
/* maximal frequency is required for Phase overflow calculation, register size is 17 bits (Nemesis) */
|
||||
@ -1843,7 +1847,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
/* keyscale code */
|
||||
CH->kcode = (blk<<2) | opn_fktable[fn >> 7];
|
||||
/* phase increment counter */
|
||||
CH->fc = ym2612.OPN.fn_table[fn*2]>>(7-blk);
|
||||
CH->fc = ym2612.OPN.fn_table[fn]>>(7-blk);
|
||||
|
||||
/* store fnum in clear form for LFO PM calculations */
|
||||
CH->block_fnum = (blk<<11) | fn;
|
||||
@ -1862,7 +1866,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
/* keyscale code */
|
||||
ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7];
|
||||
/* phase increment counter */
|
||||
ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn*2]>>(7-blk);
|
||||
ym2612.OPN.SL3.fc[c] = ym2612.OPN.fn_table[fn]>>(7-blk);
|
||||
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; //fn;
|
||||
ym2612.CH[2].SLOT[SLOT1].Incr=-1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user