mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-25 18:51:49 +01:00
[Core/Sound] added (optional) YM2612 DAC distortion emulation in MAME core & removed configurable YM2612 DAC resolution (deprecated)
This commit is contained in:
parent
b62ce884b8
commit
902dc4c4c0
@ -121,6 +121,7 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
|
||||
|
||||
[Core/Sound]
|
||||
---------------
|
||||
* added discrete YM2612 DAC distortion emulation (optional)
|
||||
* rewrote optimized & more accurate PSG core from scratch
|
||||
* removed PSG boost noise feature & added optional high-quality PSG resampling
|
||||
* fixed YM2612 self-feedback regression introduced in 1.7.1
|
||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.2 MiB |
Binary file not shown.
Before Width: | Height: | Size: 3.4 MiB After Width: | Height: | Size: 3.4 MiB |
@ -150,7 +150,7 @@ void sound_init( void )
|
||||
{
|
||||
/* MAME */
|
||||
YM2612Init();
|
||||
YM2612Config(config.dac_bits);
|
||||
YM2612Config(config.ym2612);
|
||||
YM_Reset = YM2612ResetChip;
|
||||
YM_Update = YM2612Update;
|
||||
YM_Write = YM2612Write;
|
||||
@ -288,7 +288,6 @@ int sound_context_save(uint8 *state)
|
||||
else
|
||||
{
|
||||
bufferptr += YM2612SaveContext(state + sizeof(config.ym3438));
|
||||
YM2612Config(config.dac_bits);
|
||||
}
|
||||
#else
|
||||
bufferptr = YM2612SaveContext(state);
|
||||
@ -325,11 +324,9 @@ int sound_context_load(uint8 *state)
|
||||
else
|
||||
{
|
||||
bufferptr += YM2612LoadContext(state + sizeof(config_ym3438));
|
||||
YM2612Config(config.dac_bits);
|
||||
}
|
||||
#else
|
||||
bufferptr = YM2612LoadContext(state);
|
||||
YM2612Config(config.dac_bits);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
@ -18,12 +18,16 @@
|
||||
** TODO:
|
||||
** - better documentation
|
||||
** - BUSY flag emulation
|
||||
** - accurate DAC output
|
||||
*/
|
||||
|
||||
/*
|
||||
** CHANGELOG:
|
||||
**
|
||||
** 03-12-2017 Eke-Eke (Genesis Plus GX):
|
||||
** - improved 9-bit DAC emulation accuracy
|
||||
** - added discrete YM2612 DAC distortion emulation ("ladder effect")
|
||||
** - replaced configurable DAC depth with configurable chip types (discrete, integrated or enhanced)
|
||||
**
|
||||
** 26-09-2017 Eke-Eke (Genesis Plus GX):
|
||||
** - fixed EG counter loopback behavior (verified on YM3438 die)
|
||||
** - reverted changes to EG rates 2-7 increment values
|
||||
@ -626,8 +630,11 @@ static YM2612 ym2612;
|
||||
/* current chip state */
|
||||
static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
static INT32 mem; /* one sample delay memory */
|
||||
static INT32 out_fm[8]; /* outputs of working channels */
|
||||
static UINT32 bitmask; /* working channels output bitmasking (DAC quantization) */
|
||||
static INT32 out_fm[6]; /* outputs of working channels */
|
||||
|
||||
/* chip type */
|
||||
static UINT32 op_mask[8][4]; /* operator output bitmasking (DAC quantization) */
|
||||
static int chip_type = YM2612_DISCRETE;
|
||||
|
||||
|
||||
INLINE void FM_KEYON(FM_CH *CH , int s )
|
||||
@ -1408,22 +1415,22 @@ INLINE void refresh_fc_eg_chan(FM_CH *CH )
|
||||
|
||||
#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))
|
||||
|
||||
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm)
|
||||
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
|
||||
{
|
||||
UINT32 p = (env<<3) + sin_tab[ ( (phase >> SIN_BITS) + (pm >> 1) ) & SIN_MASK ];
|
||||
|
||||
if (p >= TL_TAB_LEN)
|
||||
return 0;
|
||||
return tl_tab[p];
|
||||
return (tl_tab[p] & opmask);
|
||||
}
|
||||
|
||||
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm)
|
||||
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
|
||||
{
|
||||
UINT32 p = (env<<3) + sin_tab[ ( ( phase >> SIN_BITS ) + pm ) & SIN_MASK ];
|
||||
|
||||
if (p >= TL_TAB_LEN)
|
||||
return 0;
|
||||
return tl_tab[p];
|
||||
return (tl_tab[p] & opmask);
|
||||
}
|
||||
|
||||
INLINE void chan_calc(FM_CH *CH, int num)
|
||||
@ -1433,6 +1440,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
INT32 out = 0;
|
||||
UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams;
|
||||
unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);
|
||||
UINT32 *mask = op_mask[CH->ALGO];
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
|
||||
@ -1443,7 +1451,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
if (CH->FB < SIN_BITS)
|
||||
out = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
|
||||
|
||||
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out );
|
||||
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out, mask[0]);
|
||||
}
|
||||
|
||||
CH->op1_out[0] = CH->op1_out[1];
|
||||
@ -1459,22 +1467,21 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT3]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 3 */
|
||||
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2);
|
||||
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2, mask[2]);
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT2]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 2 */
|
||||
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1);
|
||||
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1, mask[1]);
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT4]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 4 */
|
||||
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);
|
||||
|
||||
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2, mask[3]);
|
||||
|
||||
/* store current MEM */
|
||||
CH->mem_value = mem;
|
||||
|
||||
/* update phase counters AFTER output calculations */
|
||||
if(CH->pms)
|
||||
if (CH->pms)
|
||||
{
|
||||
/* 3-slot mode */
|
||||
if ((ym2612.OPN.ST.mode & 0xC0) && (CH == &ym2612.CH[2]))
|
||||
@ -1515,7 +1522,7 @@ INLINE void OPNWriteMode(int r, int v)
|
||||
case 0x21: /* Test */
|
||||
break;
|
||||
|
||||
case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/ym2612) */
|
||||
case 0x22: /* LFO FREQ */
|
||||
if (v&8) /* LFO enabled ? */
|
||||
{
|
||||
ym2612.OPN.lfo_timer_overflow = lfo_samples_per_step[v&7];
|
||||
@ -1550,7 +1557,6 @@ INLINE void OPNWriteMode(int r, int v)
|
||||
if( c == 3 ) break;
|
||||
if (v&0x04) c+=3; /* CH 4-6 */
|
||||
CH = &ym2612.CH[c];
|
||||
|
||||
if (v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
|
||||
if (v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
|
||||
if (v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
|
||||
@ -1686,8 +1692,6 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
That is not necessary, but then EG will be generating Attack phase.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
@ -1722,7 +1726,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
|
||||
ym2612.CH[2].SLOT[SLOT1].Incr=-1;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
|
||||
if(r < 0x100)
|
||||
ym2612.OPN.SL3.fn_h = v&0x3f;
|
||||
@ -1737,7 +1741,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
CH->ALGO = v&7;
|
||||
CH->FB = SIN_BITS - ((v>>3)&7);
|
||||
setup_connection( CH, c );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS */
|
||||
/* b0-2 PMS */
|
||||
@ -1747,8 +1751,8 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];
|
||||
|
||||
/* PAN : b7 = L, b6 = R */
|
||||
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0;
|
||||
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0;
|
||||
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? 0xffffffff : 0;
|
||||
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? 0xffffffff : 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1884,6 +1888,15 @@ static void init_tables(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* build default OP mask table */
|
||||
for (i = 0;i < 8;i++)
|
||||
{
|
||||
for (d = 0;d < 4;d++)
|
||||
{
|
||||
op_mask[i][d] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2020,7 +2033,7 @@ void YM2612Update(int *buffer, int length)
|
||||
refresh_fc_eg_chan(&ym2612.CH[5]);
|
||||
|
||||
/* buffering */
|
||||
for(i=0; i<length ; i++)
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
/* clear outputs */
|
||||
out_fm[0] = 0;
|
||||
@ -2066,21 +2079,21 @@ void YM2612Update(int *buffer, int length)
|
||||
advance_eg_channels(&ym2612.CH[0], ym2612.OPN.eg_cnt);
|
||||
}
|
||||
|
||||
/* 14-bit accumulator channels outputs (range is -8192;+8192) */
|
||||
if (out_fm[0] > 8192) out_fm[0] = 8192;
|
||||
/* channels accumulator output clipping (14-bit max) */
|
||||
if (out_fm[0] > 8191) out_fm[0] = 8191;
|
||||
else if (out_fm[0] < -8192) out_fm[0] = -8192;
|
||||
if (out_fm[1] > 8192) out_fm[1] = 8192;
|
||||
if (out_fm[1] > 8191) out_fm[1] = 8191;
|
||||
else if (out_fm[1] < -8192) out_fm[1] = -8192;
|
||||
if (out_fm[2] > 8192) out_fm[2] = 8192;
|
||||
if (out_fm[2] > 8191) out_fm[2] = 8191;
|
||||
else if (out_fm[2] < -8192) out_fm[2] = -8192;
|
||||
if (out_fm[3] > 8192) out_fm[3] = 8192;
|
||||
if (out_fm[3] > 8191) out_fm[3] = 8191;
|
||||
else if (out_fm[3] < -8192) out_fm[3] = -8192;
|
||||
if (out_fm[4] > 8192) out_fm[4] = 8192;
|
||||
if (out_fm[4] > 8191) out_fm[4] = 8191;
|
||||
else if (out_fm[4] < -8192) out_fm[4] = -8192;
|
||||
if (out_fm[5] > 8192) out_fm[5] = 8192;
|
||||
if (out_fm[5] > 8191) out_fm[5] = 8191;
|
||||
else if (out_fm[5] < -8192) out_fm[5] = -8192;
|
||||
|
||||
/* stereo DAC channels outputs mixing */
|
||||
/* stereo DAC output panning & mixing */
|
||||
lt = ((out_fm[0]) & ym2612.OPN.pan[0]);
|
||||
rt = ((out_fm[0]) & ym2612.OPN.pan[1]);
|
||||
lt += ((out_fm[1]) & ym2612.OPN.pan[2]);
|
||||
@ -2094,11 +2107,34 @@ void YM2612Update(int *buffer, int length)
|
||||
lt += ((out_fm[5]) & ym2612.OPN.pan[10]);
|
||||
rt += ((out_fm[5]) & ym2612.OPN.pan[11]);
|
||||
|
||||
/* discrete YM2612 DAC */
|
||||
if (chip_type == YM2612_DISCRETE)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* DAC 'ladder effect' */
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if (out_fm[i] < 0)
|
||||
{
|
||||
/* -4 offset (-3 when not muted) on negative channel output (9-bit) */
|
||||
lt -= ((4 - (ym2612.OPN.pan[(2*i)+0] & 1)) << 5);
|
||||
rt -= ((4 - (ym2612.OPN.pan[(2*i)+1] & 1)) << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* +4 offset (when muted or not) on positive channel output (9-bit) */
|
||||
lt += (4 << 5);
|
||||
rt += (4 << 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* buffering */
|
||||
*buffer++ = lt;
|
||||
*buffer++ = rt;
|
||||
|
||||
/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */
|
||||
/* CSM mode: if CSM Key ON has occurred, CSM Key OFF need to be sent */
|
||||
/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */
|
||||
ym2612.OPN.SL3.key_csm <<= 1;
|
||||
|
||||
@ -2121,20 +2157,51 @@ void YM2612Update(int *buffer, int length)
|
||||
INTERNAL_TIMER_B(length);
|
||||
}
|
||||
|
||||
void YM2612Config(unsigned char dac_bits)
|
||||
void YM2612Config(int type)
|
||||
{
|
||||
int i;
|
||||
/* YM2612 chip type */
|
||||
chip_type = type;
|
||||
|
||||
/* DAC precision (normally 9-bit on real hardware, implemented through simple 14-bit channel output bitmasking) */
|
||||
bitmask = ~((1 << (TL_BITS - dac_bits)) - 1);
|
||||
|
||||
/* update L/R panning bitmasks */
|
||||
for (i=0; i<2*6; i++)
|
||||
/* carrier operator outputs bitmask */
|
||||
if (chip_type < YM2612_ENHANCED)
|
||||
{
|
||||
if (ym2612.OPN.pan[i])
|
||||
{
|
||||
ym2612.OPN.pan[i] = bitmask;
|
||||
}
|
||||
/* 9-bit DAC */
|
||||
op_mask[0][3] = 0xffffffe0;
|
||||
op_mask[1][3] = 0xffffffe0;
|
||||
op_mask[2][3] = 0xffffffe0;
|
||||
op_mask[3][3] = 0xffffffe0;
|
||||
op_mask[4][1] = 0xffffffe0;
|
||||
op_mask[4][3] = 0xffffffe0;
|
||||
op_mask[5][1] = 0xffffffe0;
|
||||
op_mask[5][2] = 0xffffffe0;
|
||||
op_mask[5][3] = 0xffffffe0;
|
||||
op_mask[6][1] = 0xffffffe0;
|
||||
op_mask[6][2] = 0xffffffe0;
|
||||
op_mask[6][3] = 0xffffffe0;
|
||||
op_mask[7][0] = 0xffffffe0;
|
||||
op_mask[7][1] = 0xffffffe0;
|
||||
op_mask[7][2] = 0xffffffe0;
|
||||
op_mask[7][3] = 0xffffffe0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 14-bit DAC */
|
||||
op_mask[0][3] = 0xffffffff;
|
||||
op_mask[1][3] = 0xffffffff;
|
||||
op_mask[2][3] = 0xffffffff;
|
||||
op_mask[3][3] = 0xffffffff;
|
||||
op_mask[4][1] = 0xffffffff;
|
||||
op_mask[4][3] = 0xffffffff;
|
||||
op_mask[5][1] = 0xffffffff;
|
||||
op_mask[5][2] = 0xffffffff;
|
||||
op_mask[5][3] = 0xffffffff;
|
||||
op_mask[6][1] = 0xffffffff;
|
||||
op_mask[6][2] = 0xffffffff;
|
||||
op_mask[6][3] = 0xffffffff;
|
||||
op_mask[7][0] = 0xffffffff;
|
||||
op_mask[7][1] = 0xffffffff;
|
||||
op_mask[7][2] = 0xffffffff;
|
||||
op_mask[7][3] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,14 @@
|
||||
#ifndef _H_YM2612_
|
||||
#define _H_YM2612_
|
||||
|
||||
enum {
|
||||
YM2612_DISCRETE = 0,
|
||||
YM2612_INTEGRATED,
|
||||
YM2612_ENHANCED
|
||||
};
|
||||
|
||||
extern void YM2612Init(void);
|
||||
extern void YM2612Config(unsigned char dac_bits);
|
||||
extern void YM2612Config(int type);
|
||||
extern void YM2612ResetChip(void);
|
||||
extern void YM2612Update(int *buffer, int length);
|
||||
extern void YM2612Write(unsigned int a, unsigned int v);
|
||||
|
@ -49,8 +49,8 @@ void set_config_defaults(void)
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.dac_bits = 14;
|
||||
config.lp_range = 0x7fff; /* 0.5 in 0.16 fixed point */
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 1; /* = AUTO (0 = always OFF, 1 = always ON) */
|
||||
config.mono = 0;
|
||||
|
||||
|
@ -21,7 +21,7 @@ typedef struct
|
||||
uint8 hq_fm;
|
||||
uint8 filter;
|
||||
uint8 hq_psg;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2612;
|
||||
uint8 ym2413;
|
||||
int16 psg_preamp;
|
||||
int16 fm_preamp;
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Genesis Plus GX configuration file support
|
||||
*
|
||||
* Copyright Eke-Eke (2007-2016)
|
||||
* Copyright Eke-Eke (2007-2017)
|
||||
*
|
||||
* Redistribution and use of this code or any derivative works are permitted
|
||||
* provided that the following conditions are met:
|
||||
@ -103,13 +103,13 @@ void config_default(void)
|
||||
config.hq_fm = 1;
|
||||
config.hq_psg = 1;
|
||||
config.filter = 1;
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.lp_range = 0x7FFF; /* 0.5 in 0.16 fixed point */
|
||||
config.low_freq = 880;
|
||||
config.high_freq = 5000;
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.dac_bits = 14;
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 2; /* AUTO */
|
||||
config.mono = 0;
|
||||
|
||||
|
@ -52,7 +52,7 @@ typedef struct
|
||||
uint8 hq_fm;
|
||||
uint8 filter;
|
||||
uint8 hq_psg;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2612;
|
||||
uint8 ym2413;
|
||||
uint8 mono;
|
||||
int16 psg_preamp;
|
||||
|
@ -343,20 +343,20 @@ static gui_item items_options[] =
|
||||
/* Audio options */
|
||||
static gui_item items_audio[] =
|
||||
{
|
||||
{NULL,NULL,"Master System FM: AUTO", "Enable/Disable YM2413 chip", 56,132,276,48},
|
||||
{NULL,NULL,"High-Quality FM: ON", "Enable/Disable YM2612/YM2413 high-quality resampling", 56,132,276,48},
|
||||
{NULL,NULL,"FM Resolution: MAX", "Adjust YM2612 DAC precision", 56,132,276,48},
|
||||
{NULL,NULL,"FM Volume: 1.00", "Adjust YM2612/YM2413 audio balance", 56,132,276,48},
|
||||
{NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 audio balance", 56,132,276,48},
|
||||
{NULL,NULL,"High-Quality PSG: ON", "Enable/Disable SN76489 high-quality resampling", 56,132,276,48},
|
||||
{NULL,NULL,"Audio Output: STEREO", "Select audio mixing output type", 56,132,276,48},
|
||||
{NULL,NULL,"Filtering: 3-BAND EQ", "Select audio filtering type", 56,132,276,48},
|
||||
{NULL,NULL,"Low Gain: 1.00", "Adjust EQ Low Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"Mid Gain: 1.00", "Adjust EQ Mid Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"High Gain: 1.00", "Adjust EQ High Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"Low Freq: 200 Hz", "Adjust EQ Lowest Frequency", 56,132,276,48},
|
||||
{NULL,NULL,"High Freq: 20000 Hz", "Adjust EQ Highest Frequency", 56,132,276,48}
|
||||
};
|
||||
{NULL,NULL,"Master System FM: AUTO", "Enable/Disable YM2413 chip", 56,132,276,48},
|
||||
{NULL,NULL,"YM2612 Type: DISCRETE", "Select YM2612 chip model", 56,132,276,48},
|
||||
{NULL,NULL,"High-Quality FM: ON", "Enable/Disable YM2612/YM2413 high-quality resampling", 56,132,276,48},
|
||||
{NULL,NULL,"High-Quality PSG: ON", "Enable/Disable SN76489 high-quality resampling", 56,132,276,48},
|
||||
{NULL,NULL,"FM Volume: 1.00", "Adjust YM2612/YM2413 audio balance", 56,132,276,48},
|
||||
{NULL,NULL,"PSG Volume: 2.50", "Adjust SN76489 audio balance", 56,132,276,48},
|
||||
{NULL,NULL,"Audio Output: STEREO", "Select audio mixing output type", 56,132,276,48},
|
||||
{NULL,NULL,"Filtering: 3-BAND EQ", "Select audio filtering type", 56,132,276,48},
|
||||
{NULL,NULL,"Low Gain: 1.00", "Adjust EQ Low Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"Mid Gain: 1.00", "Adjust EQ Mid Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"High Gain: 1.00", "Adjust EQ High Band Gain", 56,132,276,48},
|
||||
{NULL,NULL,"Low Freq: 200 Hz", "Adjust EQ Lowest Frequency", 56,132,276,48},
|
||||
{NULL,NULL,"High Freq: 20000 Hz", "Adjust EQ Highest Frequency", 56,132,276,48}
|
||||
};
|
||||
|
||||
/* System ROM paths */
|
||||
static gui_item items_rompaths[] =
|
||||
@ -901,14 +901,16 @@ static void soundmenu ()
|
||||
else if (config.ym2413 == 1) sprintf (items[0].text, "Master System FM: ON");
|
||||
else sprintf (items[0].text, "Master System FM: AUTO");
|
||||
|
||||
sprintf (items[1].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||
if (config.ym2612 == YM2612_DISCRETE) sprintf (items[1].text, "YM2612 Type: DISCRETE");
|
||||
else if (config.ym2612 == YM2612_INTEGRATED) sprintf (items[1].text, "YM2612 Type: ASIC");
|
||||
else sprintf (items[1].text, "YM2612 Type: ENHANCED");
|
||||
|
||||
if (config.dac_bits < 14) sprintf (items[2].text, "FM Resolution: %d bits", config.dac_bits);
|
||||
else sprintf (items[2].text, "FM Resolution: MAX");
|
||||
sprintf (items[2].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||
sprintf (items[3].text, "High-Quality PSG: %s", config.hq_psg? "ON":"OFF");
|
||||
|
||||
sprintf (items[4].text, "FM Volume: %1.2f", fm_volume);
|
||||
sprintf (items[5].text, "PSG Volume: %1.2f", psg_volume);
|
||||
|
||||
sprintf (items[3].text, "FM Volume: %1.2f", fm_volume);
|
||||
sprintf (items[4].text, "PSG Volume: %1.2f", psg_volume);
|
||||
sprintf (items[5].text, "High-Quality PSG: %s", config.hq_psg? "ON":"OFF");
|
||||
sprintf (items[6].text, "Audio Output: %s", config.mono ? "MONO":"STEREO");
|
||||
|
||||
if (config.filter == 2)
|
||||
@ -971,33 +973,41 @@ static void soundmenu ()
|
||||
|
||||
case 1:
|
||||
{
|
||||
config.hq_fm ^= 1;
|
||||
sprintf (items[1].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||
config.ym2612++;
|
||||
if (config.ym2612 > YM2612_ENHANCED) config.ym2612 = YM2612_DISCRETE;
|
||||
if (config.ym2612 == YM2612_DISCRETE) sprintf (items[1].text, "YM2612 Type: DISCRETE");
|
||||
else if (config.ym2612 == YM2612_INTEGRATED) sprintf (items[1].text, "YM2612 Type: ASIC");
|
||||
else sprintf (items[1].text, "YM2612 Type: ENHANCED");
|
||||
YM2612Config(config.ym2612);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
config.dac_bits++;
|
||||
if (config.dac_bits > 14) config.dac_bits = 7;
|
||||
if (config.dac_bits < 14) sprintf (items[2].text, "FM Resolution: %d bits", config.dac_bits);
|
||||
else sprintf (items[2].text, "FM Resolution: MAX");
|
||||
YM2612Config(config.dac_bits);
|
||||
config.hq_fm ^= 1;
|
||||
sprintf (items[2].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
|
||||
sprintf (items[3].text, "FM Volume: %1.2f", fm_volume);
|
||||
config.fm_preamp = (int)(fm_volume * 100.0 + 0.5);
|
||||
config.hq_psg ^= 1;
|
||||
sprintf (items[3].text, "High-Quality PSG: %s", config.hq_psg ? "ON":"OFF");
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
GUI_OptionBox(m,0,"FM Volume",(void *)&fm_volume,0.01,0.0,5.0,0);
|
||||
sprintf (items[4].text, "FM Volume: %1.2f", fm_volume);
|
||||
config.fm_preamp = (int)(fm_volume * 100.0 + 0.5);
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
GUI_OptionBox(m,0,"PSG Volume",(void *)&psg_volume,0.01,0.0,5.0,0);
|
||||
sprintf (items[4].text, "PSG Volume: %1.2f", psg_volume);
|
||||
sprintf (items[5].text, "PSG Volume: %1.2f", psg_volume);
|
||||
config.psg_preamp = (int)(psg_volume * 100.0 + 0.5);
|
||||
if ((system_hw & SYSTEM_PBC) == SYSTEM_MD)
|
||||
{
|
||||
@ -1010,13 +1020,6 @@ static void soundmenu ()
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
config.hq_psg ^= 1;
|
||||
sprintf (items[5].text, "High-Quality PSG: %s", config.hq_psg ? "ON":"OFF");
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
config.mono ^= 1;
|
||||
|
@ -533,15 +533,18 @@ static void config_default(void)
|
||||
config.hq_fm = 1; /* high-quality FM resampling (slower) */
|
||||
config.hq_psg = 1; /* high-quality PSG resampling (slower) */
|
||||
config.filter = 0; /* no filter */
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.lp_range = 0x7fff; /* 0.5 in 0.16 fixed point */
|
||||
config.low_freq = 880;
|
||||
config.high_freq = 5000;
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.dac_bits = 14; /* MAX DEPTH */
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 2; /* AUTO */
|
||||
config.mono = 0; /* STEREO output */
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
config.ym3438 = 0;
|
||||
#endif
|
||||
|
||||
/* system options */
|
||||
config.system = 0; /* AUTO */
|
||||
@ -1104,10 +1107,10 @@ static void check_variables(void)
|
||||
if (!strcmp(var.value, "low-pass"))
|
||||
config.filter = 1;
|
||||
|
||||
#if HAVE_EQ
|
||||
#if HAVE_EQ
|
||||
else if (!strcmp(var.value, "EQ"))
|
||||
config.filter = 2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
else
|
||||
config.filter = 0;
|
||||
@ -1117,9 +1120,9 @@ static void check_variables(void)
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
config.lp_range = (atoi(var.value) * 65536) / 100;
|
||||
}
|
||||
|
||||
#if HAVE_EQ
|
||||
}
|
||||
|
||||
#if HAVE_EQ
|
||||
var.key = "genesis_plus_gx_audio_eq_low";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
@ -1127,7 +1130,7 @@ static void check_variables(void)
|
||||
if (new_lg != config.lg) restart_eq = true;
|
||||
config.lg = new_lg;
|
||||
}
|
||||
|
||||
|
||||
var.key = "genesis_plus_gx_audio_eq_mid";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
@ -1135,7 +1138,7 @@ static void check_variables(void)
|
||||
if (new_mg != config.mg) restart_eq = true;
|
||||
config.mg = new_mg;
|
||||
}
|
||||
|
||||
|
||||
var.key = "genesis_plus_gx_audio_eq_high";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
@ -1144,23 +1147,12 @@ static void check_variables(void)
|
||||
config.hg = new_hg;
|
||||
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
var.key = "genesis_plus_gx_dac_bits";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
if (!strcmp(var.value, "enabled"))
|
||||
config.dac_bits = 9;
|
||||
else
|
||||
config.dac_bits = 14;
|
||||
|
||||
YM2612Config(config.dac_bits);
|
||||
}
|
||||
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
var.key = "genesis_plus_gx_ym3438";
|
||||
var.key = "genesis_plus_gx_ym2612";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
orig_value = config.ym3438;
|
||||
if (!strcmp(var.value, "nuked (ym2612)"))
|
||||
{
|
||||
@ -1178,15 +1170,33 @@ static void check_variables(void)
|
||||
config.ym3438 = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.ym3438 = 0;
|
||||
}
|
||||
|
||||
if (orig_value == 0 && config.ym3438 > 0 || orig_value > 0 && config.ym3438 == 0)
|
||||
if (((orig_value == 0) && (config.ym3438 > 0)) || ((orig_value > 0) && (config.ym3438 == 0)))
|
||||
{
|
||||
sound_init();
|
||||
sound_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!strcmp(var.value, "mame (ym2612)"))
|
||||
{
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
YM2612Config(YM2612_DISCRETE);
|
||||
}
|
||||
else if (!strcmp(var.value, "mame (asic ym3438)"))
|
||||
{
|
||||
config.ym2612 = YM2612_INTEGRATED;
|
||||
YM2612Config(YM2612_INTEGRATED);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.ym2612 = YM2612_ENHANCED;
|
||||
YM2612Config(YM2612_ENHANCED);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var.key = "genesis_plus_gx_blargg_ntsc_filter";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
@ -1754,11 +1764,12 @@ void retro_set_environment(retro_environment_t cb)
|
||||
{ "genesis_plus_gx_bram", "CD System BRAM; per bios|per game" },
|
||||
{ "genesis_plus_gx_addr_error", "68k address error; enabled|disabled" },
|
||||
{ "genesis_plus_gx_lock_on", "Cartridge lock-on; disabled|game genie|action replay (pro)|sonic & knuckles" },
|
||||
{ "genesis_plus_gx_ym2413", "Master System FM; auto|disabled|enabled" },
|
||||
{ "genesis_plus_gx_dac_bits", "YM2612 DAC quantization; disabled|enabled" },
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
{ "genesis_plus_gx_ym3438", "YM2612/YM3438 core; mame|nuked (ym2612)|nuked (asic ym3438)|nuked (discrete ym3438)" },
|
||||
#endif
|
||||
{ "genesis_plus_gx_ym2413", "Master System FM (YM2413); auto|disabled|enabled" },
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
{ "genesis_plus_gx_ym2612", "Mega Drive / Genesis FM; mame (ym2612)|mame (asic ym3438)|mame (enhanced ym3438)|nuked (ym2612)|nuked (asic ym3438)|nuked (discrete ym3438)" },
|
||||
#else
|
||||
{ "genesis_plus_gx_ym2612", "Mega Drive / Genesis FM; mame (ym2612)|mame (asic ym3438)|mame (enhanced ym3438)" },
|
||||
#endif
|
||||
|
||||
{ "genesis_plus_gx_sound_output", "Sound output; stereo|mono" },
|
||||
{ "genesis_plus_gx_audio_filter", "Audio filter; disabled|low-pass" },
|
||||
|
@ -94,7 +94,7 @@ struct
|
||||
uint8 hq_fm;
|
||||
uint8 filter;
|
||||
uint8 hq_psg;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2612;
|
||||
uint8 ym2413;
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
uint8 ym3438;
|
||||
|
@ -18,8 +18,8 @@ void set_config_defaults(void)
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.dac_bits = 14;
|
||||
config.lp_range = 0x7fff; /* 0.5 in 0.16 fixed point */
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 2; /* = AUTO (0 = always OFF, 1 = always ON) */
|
||||
config.mono = 0;
|
||||
|
||||
|
@ -20,7 +20,7 @@ typedef struct
|
||||
uint8 hq_fm;
|
||||
uint8 filter;
|
||||
uint8 hq_psg;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2612;
|
||||
uint8 ym2413;
|
||||
int16 psg_preamp;
|
||||
int16 fm_preamp;
|
||||
|
@ -19,8 +19,8 @@ void set_config_defaults(void)
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.dac_bits = 14;
|
||||
config.lp_range = 0x7fff; /* 0.6 in 0.16 fixed point */
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 2; /* = AUTO (0 = always OFF, 1 = always ON) */
|
||||
config.ym3438 = 0;
|
||||
config.mono = 0;
|
||||
|
@ -16,7 +16,7 @@ typedef struct
|
||||
uint8 hq_fm;
|
||||
uint8 filter;
|
||||
uint8 hq_psg;
|
||||
uint8 dac_bits;
|
||||
uint8 ym2612;
|
||||
uint8 ym2413;
|
||||
uint8 ym3438;
|
||||
int16 psg_preamp;
|
||||
|
Loading…
Reference in New Issue
Block a user