mirror of
https://github.com/holub/mame
synced 2025-05-22 05:38:52 +03:00
> From: atari_ace@frontier.com
> To: submit@mamedev.org > CC: atariace@hotmail.com > Subject: [patch] Improve thread safety of FM sound cores > Date: Sun, 7 Nov 2010 08:50:36 -0800 > > Hi mamedev, > > Most of the FM sound cores still have some static state in them which > means they are not multithread safe. This patch fixes this. > > ~aa
This commit is contained in:
parent
b4cc7cc7c1
commit
4b2de92fba
@ -652,27 +652,28 @@ typedef struct
|
||||
UINT32 fn_max; /* maximal phase increment (used for phase overflow) */
|
||||
|
||||
/* LFO */
|
||||
UINT32 LFO_AM; /* runtime LFO calculations helper */
|
||||
INT32 LFO_PM; /* runtime LFO calculations helper */
|
||||
|
||||
UINT32 lfo_cnt;
|
||||
UINT32 lfo_inc;
|
||||
|
||||
UINT32 lfo_freq[8]; /* LFO FREQ table */
|
||||
|
||||
INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
INT32 mem; /* one sample delay memory */
|
||||
|
||||
INT32 out_fm[8]; /* outputs of working channels */
|
||||
|
||||
#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
|
||||
INT32 out_adpcm[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 ADPCM */
|
||||
INT32 out_delta[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 DELTAT*/
|
||||
#endif
|
||||
} FM_OPN;
|
||||
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
#if (BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
|
||||
static INT32 out_adpcm[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 ADPCM */
|
||||
static INT32 out_delta[4]; /* channel output NONE,LEFT,RIGHT or CENTER for YM2608/YM2610 DELTAT*/
|
||||
#endif
|
||||
|
||||
static UINT32 LFO_AM; /* runtime LFO calculations helper */
|
||||
static INT32 LFO_PM; /* runtime LFO calculations helper */
|
||||
|
||||
/* log output level */
|
||||
#define LOG_ERR 3 /* ERROR */
|
||||
@ -885,9 +886,9 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
|
||||
}
|
||||
|
||||
/* set algorithm connection */
|
||||
static void setup_connection( FM_CH *CH, int ch )
|
||||
static void setup_connection( FM_OPN *OPN, FM_CH *CH, int ch )
|
||||
{
|
||||
INT32 *carrier = &out_fm[ch];
|
||||
INT32 *carrier = &OPN->out_fm[ch];
|
||||
|
||||
INT32 **om1 = &CH->connect1;
|
||||
INT32 **om2 = &CH->connect3;
|
||||
@ -895,46 +896,47 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
|
||||
INT32 **memc = &CH->mem_connect;
|
||||
|
||||
switch( CH->ALGO ){
|
||||
switch( CH->ALGO )
|
||||
{
|
||||
case 0:
|
||||
/* M1---C1---MEM---M2---C2---OUT */
|
||||
*om1 = &c1;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 1:
|
||||
/* M1------+-MEM---M2---C2---OUT */
|
||||
/* C1-+ */
|
||||
*om1 = &mem;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->mem;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 2:
|
||||
/* M1-----------------+-C2---OUT */
|
||||
/* C1---MEM---M2-+ */
|
||||
*om1 = &c2;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->c2;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 3:
|
||||
/* M1---C1---MEM------+-C2---OUT */
|
||||
/* M2-+ */
|
||||
*om1 = &c1;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &c2;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->c2;
|
||||
break;
|
||||
case 4:
|
||||
/* M1---C1-+-OUT */
|
||||
/* M2---C2-+ */
|
||||
/* MEM: not used */
|
||||
*om1 = &c1;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = carrier;
|
||||
*om2 = &c2;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
case 5:
|
||||
/* +----C1----+ */
|
||||
@ -943,17 +945,17 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
*om1 = 0; /* special mark */
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &m2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 6:
|
||||
/* M1---C1-+ */
|
||||
/* M2-+-OUT */
|
||||
/* C2-+ */
|
||||
/* MEM: not used */
|
||||
*om1 = &c1;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
case 7:
|
||||
/* M1-+ */
|
||||
@ -964,7 +966,7 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
*om1 = carrier;
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1085,9 +1087,9 @@ INLINE void advance_lfo(FM_OPN *OPN)
|
||||
/* triangle */
|
||||
/* AM: 0 to 126 step +2, 126 to 0 step -2 */
|
||||
if (pos<64)
|
||||
LFO_AM = (pos&63) * 2;
|
||||
OPN->LFO_AM = (pos&63) * 2;
|
||||
else
|
||||
LFO_AM = 126 - ((pos&63) * 2);
|
||||
OPN->LFO_AM = 126 - ((pos&63) * 2);
|
||||
}
|
||||
|
||||
/* PM works with 4 times slower clock */
|
||||
@ -1095,14 +1097,14 @@ INLINE void advance_lfo(FM_OPN *OPN)
|
||||
/* 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*/
|
||||
{
|
||||
LFO_PM = pos;
|
||||
OPN->LFO_PM = pos;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LFO_AM = 0;
|
||||
LFO_PM = 0;
|
||||
OPN->LFO_AM = 0;
|
||||
OPN->LFO_PM = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1261,7 +1263,7 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
|
||||
INLINE void update_phase_lfo_slot(FM_OPN *OPN, 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 ];
|
||||
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + pms + OPN->LFO_PM ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
@ -1297,7 +1299,7 @@ INLINE void update_phase_lfo_channel(FM_OPN *OPN, 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 ];
|
||||
INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + CH->pms + OPN->LFO_PM ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
@ -1347,10 +1349,10 @@ INLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum)
|
||||
{
|
||||
unsigned int eg_out;
|
||||
|
||||
UINT32 AM = LFO_AM >> CH->ams;
|
||||
UINT32 AM = OPN->LFO_AM >> CH->ams;
|
||||
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
OPN->m2 = OPN->c1 = OPN->c2 = OPN->mem = 0;
|
||||
|
||||
*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
|
||||
@ -1359,9 +1361,10 @@ INLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum)
|
||||
INT32 out = CH->op1_out[0] + CH->op1_out[1];
|
||||
CH->op1_out[0] = CH->op1_out[1];
|
||||
|
||||
if( !CH->connect1 ){
|
||||
if( !CH->connect1 )
|
||||
{
|
||||
/* algorithm 5 */
|
||||
mem = c1 = c2 = CH->op1_out[0];
|
||||
OPN->mem = OPN->c1 = OPN->c2 = CH->op1_out[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1381,19 +1384,19 @@ INLINE void chan_calc(FM_OPN *OPN, FM_CH *CH, int chnum)
|
||||
|
||||
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, OPN->m2);
|
||||
|
||||
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, OPN->c1);
|
||||
|
||||
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, OPN->c2);
|
||||
|
||||
|
||||
/* store current MEM */
|
||||
CH->mem_value = mem;
|
||||
CH->mem_value = OPN->mem;
|
||||
|
||||
/* update phase counters AFTER output calculations */
|
||||
if(CH->pms)
|
||||
@ -1460,7 +1463,8 @@ INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )
|
||||
/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */
|
||||
static void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH )
|
||||
{
|
||||
if( CH->SLOT[SLOT1].Incr==-1){
|
||||
if( CH->SLOT[SLOT1].Incr==-1)
|
||||
{
|
||||
int fc = CH->fc;
|
||||
int kc = CH->kcode;
|
||||
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc );
|
||||
@ -1482,8 +1486,10 @@ static void init_timetables( FM_ST *ST , const UINT8 *dttable )
|
||||
#endif
|
||||
|
||||
/* DeTune table */
|
||||
for (d = 0;d <= 3;d++){
|
||||
for (i = 0;i <= 31;i++){
|
||||
for (d = 0;d <= 3;d++)
|
||||
{
|
||||
for (i = 0;i <= 31;i++)
|
||||
{
|
||||
rate = ((double)dttable[d*32 + i]) * SIN_LEN * ST->freqbase * (1<<FREQ_SH) / ((double)(1<<20));
|
||||
ST->dt_tab[d][i] = (INT32) rate;
|
||||
ST->dt_tab[d+4][i] = -ST->dt_tab[d][i];
|
||||
@ -1783,7 +1789,8 @@ static void OPNWriteMode(FM_OPN *OPN, int r, int v)
|
||||
UINT8 c;
|
||||
FM_CH *CH;
|
||||
|
||||
switch(r){
|
||||
switch(r)
|
||||
{
|
||||
case 0x21: /* Test */
|
||||
break;
|
||||
case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
|
||||
@ -1842,7 +1849,8 @@ static void OPNWriteReg(FM_OPN *OPN, int r, int v)
|
||||
|
||||
SLOT = &(CH->SLOT[OPN_SLOT(r)]);
|
||||
|
||||
switch( r & 0xf0 ) {
|
||||
switch( r & 0xf0 )
|
||||
{
|
||||
case 0x30: /* DET , MUL */
|
||||
set_det_mul(&OPN->ST,CH,SLOT,v);
|
||||
break;
|
||||
@ -1954,7 +1962,8 @@ static void OPNWriteReg(FM_OPN *OPN, int r, int v)
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
switch( OPN_SLOT(r) ){
|
||||
switch( OPN_SLOT(r) )
|
||||
{
|
||||
case 0: /* 0xa0-0xa2 : FNUM1 */
|
||||
{
|
||||
UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;
|
||||
@ -1994,13 +2003,14 @@ static void OPNWriteReg(FM_OPN *OPN, int r, int v)
|
||||
break;
|
||||
|
||||
case 0xb0:
|
||||
switch( OPN_SLOT(r) ){
|
||||
switch( OPN_SLOT(r) )
|
||||
{
|
||||
case 0: /* 0xb0-0xb2 : FB,ALGO */
|
||||
{
|
||||
int feedback = (v>>3)&7;
|
||||
CH->ALGO = v&7;
|
||||
CH->FB = feedback ? feedback+6 : 0;
|
||||
setup_connection( CH, c );
|
||||
setup_connection( OPN, CH, c );
|
||||
}
|
||||
break;
|
||||
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
|
||||
@ -2114,20 +2124,22 @@ void ym2203_update_one(void *chip, FMSAMPLE *buffer, int length)
|
||||
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, cch[2] );
|
||||
}
|
||||
else
|
||||
refresh_fc_eg_chan( OPN, cch[2] );
|
||||
|
||||
|
||||
/* YM2203 doesn't have LFO so we must keep these globals at 0 level */
|
||||
LFO_AM = 0;
|
||||
LFO_PM = 0;
|
||||
OPN->LFO_AM = 0;
|
||||
OPN->LFO_PM = 0;
|
||||
|
||||
/* buffering */
|
||||
for (i=0; i < length ; i++)
|
||||
{
|
||||
/* clear outputs */
|
||||
out_fm[0] = 0;
|
||||
out_fm[1] = 0;
|
||||
out_fm[2] = 0;
|
||||
OPN->out_fm[0] = 0;
|
||||
OPN->out_fm[1] = 0;
|
||||
OPN->out_fm[2] = 0;
|
||||
|
||||
/* advance envelope generator */
|
||||
OPN->eg_timer += OPN->eg_timer_add;
|
||||
@ -2150,7 +2162,7 @@ void ym2203_update_one(void *chip, FMSAMPLE *buffer, int length)
|
||||
{
|
||||
int lt;
|
||||
|
||||
lt = out_fm[0] + out_fm[1] + out_fm[2];
|
||||
lt = OPN->out_fm[0] + OPN->out_fm[1] + OPN->out_fm[2];
|
||||
|
||||
lt >>= FINAL_SH;
|
||||
|
||||
@ -2422,10 +2434,6 @@ typedef YM2610 YM2608;
|
||||
#define ADPCM_SHIFT (16) /* frequency step rate */
|
||||
#define ADPCMA_ADDRESS_SHIFT 8 /* adpcm A address shift */
|
||||
|
||||
static const UINT8 *pcmbufA;
|
||||
static UINT32 pcmsizeA;
|
||||
|
||||
|
||||
/* Algorithm and tables verified on real YM2608 and YM2610 */
|
||||
|
||||
/* usual ADPCM table (16 * 1.1^N) */
|
||||
@ -2447,8 +2455,8 @@ static const int step_inc[8] = { -1*16, -1*16, -1*16, -1*16, 2*16, 5*16, 7*16, 9
|
||||
static int jedi_table[ 49*16 ];
|
||||
|
||||
|
||||
static void Init_ADPCMATable(void){
|
||||
|
||||
static void Init_ADPCMATable(void)
|
||||
{
|
||||
int step, nib;
|
||||
|
||||
for (step = 0; step < 49; step++)
|
||||
@ -2487,7 +2495,8 @@ INLINE void ADPCMA_calc_chan( YM2610 *F2610, ADPCM_CH *ch )
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
if ( ch->now_addr > (pcmsizeA<<1) ) {
|
||||
if ( ch->now_addr > (F2610->pcmsizeA<<1) )
|
||||
{
|
||||
LOG(LOG_WAR,("YM2610: Attempting to play past adpcm rom size!\n" ));
|
||||
return;
|
||||
}
|
||||
@ -2496,7 +2505,7 @@ INLINE void ADPCMA_calc_chan( YM2610 *F2610, ADPCM_CH *ch )
|
||||
data = ch->now_data & 0x0f;
|
||||
else
|
||||
{
|
||||
ch->now_data = *(pcmbufA+(ch->now_addr>>1));
|
||||
ch->now_data = *(F2610->pcmbuf+(ch->now_addr>>1));
|
||||
data = (ch->now_data >> 4) & 0x0f;
|
||||
}
|
||||
|
||||
@ -2530,7 +2539,8 @@ static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
|
||||
UINT8 c = r&0x07;
|
||||
|
||||
F2610->adpcmreg[r] = v&0xff; /* stock data */
|
||||
switch( r ){
|
||||
switch( r )
|
||||
{
|
||||
case 0x00: /* DM,--,C5,C4,C3,C2,C1,C0 */
|
||||
if( !(v&0x80) )
|
||||
{
|
||||
@ -2548,11 +2558,15 @@ static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
|
||||
adpcm[c].adpcm_out = 0;
|
||||
adpcm[c].flag = 1;
|
||||
|
||||
if(F2610->pcmbuf==NULL){ /* Check ROM Mapped */
|
||||
if(F2610->pcmbuf==NULL)
|
||||
{ /* Check ROM Mapped */
|
||||
logerror("YM2608-YM2610: ADPCM-A rom not mapped\n");
|
||||
adpcm[c].flag = 0;
|
||||
} else{
|
||||
if(adpcm[c].end >= F2610->pcm_size){ /* Check End in Range */
|
||||
}
|
||||
else
|
||||
{
|
||||
if(adpcm[c].end >= F2610->pcm_size)
|
||||
{ /* Check End in Range */
|
||||
logerror("YM2610: ADPCM-A end out of range: $%08x\n",adpcm[c].end);
|
||||
/*adpcm[c].end = F2610->pcm_size-1;*/ /* JB: DO NOT uncomment this, otherwise you will break the comparison in the ADPCM_CALC_CHA() */
|
||||
}
|
||||
@ -2597,7 +2611,8 @@ static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
|
||||
default:
|
||||
c = r&0x07;
|
||||
if( c >= 0x06 ) return;
|
||||
switch( r&0x38 ){
|
||||
switch( r&0x38 )
|
||||
{
|
||||
case 0x08: /* B7=L,B6=R, B4-0=IL */
|
||||
{
|
||||
int volume;
|
||||
@ -2617,7 +2632,7 @@ static void FM_ADPCMAWrite(YM2610 *F2610,int r,int v)
|
||||
adpcm[c].vol_shift = 1 + (volume >> 3); /* Yamaha engineers used the approximation: each -6 dB is close to divide by two (shift right) */
|
||||
}
|
||||
|
||||
adpcm[c].pan = &out_adpcm[(v>>6)&0x03];
|
||||
adpcm[c].pan = &F2610->OPN.out_adpcm[(v>>6)&0x03];
|
||||
|
||||
/* calc pcm * volume data */
|
||||
adpcm[c].adpcm_out = ((adpcm[c].adpcm_acc * adpcm[c].vol_mul) >> adpcm[c].vol_shift) & ~3; /* multiply, shift and mask out low 2 bits */
|
||||
@ -3260,6 +3275,7 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
int i,j;
|
||||
FMSAMPLE *bufL,*bufR;
|
||||
FM_CH *cch[6];
|
||||
INT32 *out_fm = OPN->out_fm;
|
||||
|
||||
/* set bufer */
|
||||
bufL = buffer[0];
|
||||
@ -3271,9 +3287,6 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
cch[3] = &F2608->CH[3];
|
||||
cch[4] = &F2608->CH[4];
|
||||
cch[5] = &F2608->CH[5];
|
||||
/* setup adpcm rom address */
|
||||
pcmbufA = F2608->pcmbuf;
|
||||
pcmsizeA = F2608->pcm_size;
|
||||
|
||||
/* refresh PG and EG */
|
||||
refresh_fc_eg_chan( OPN, cch[0] );
|
||||
@ -3288,7 +3301,9 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
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, cch[2] );
|
||||
}
|
||||
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] );
|
||||
@ -3301,8 +3316,8 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
advance_lfo(OPN);
|
||||
|
||||
/* clear output acc. */
|
||||
out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
|
||||
out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
|
||||
OPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;
|
||||
OPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;
|
||||
/* clear outputs */
|
||||
out_fm[0] = 0;
|
||||
out_fm[1] = 0;
|
||||
@ -3349,10 +3364,10 @@ void ym2608_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
{
|
||||
int lt,rt;
|
||||
|
||||
lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER];
|
||||
rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
|
||||
lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9;
|
||||
rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9;
|
||||
lt = OPN->out_adpcm[OUTD_LEFT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
rt = OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
lt += (OPN->out_delta[OUTD_LEFT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
rt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
lt += ((out_fm[0]>>1) & OPN->pan[0]); /* shift right verified on real YM2608 */
|
||||
rt += ((out_fm[0]>>1) & OPN->pan[1]);
|
||||
lt += ((out_fm[1]>>1) & OPN->pan[2]);
|
||||
@ -3588,7 +3603,7 @@ void ym2608_reset_chip(void *chip)
|
||||
F2608->adpcm[i].now_step = 0;
|
||||
/* F2608->adpcm[i].delta = 21866; */
|
||||
F2608->adpcm[i].vol_mul = 0;
|
||||
F2608->adpcm[i].pan = &out_adpcm[OUTD_CENTER]; /* default center */
|
||||
F2608->adpcm[i].pan = &OPN->out_adpcm[OUTD_CENTER]; /* default center */
|
||||
F2608->adpcm[i].flagMask = 0;
|
||||
F2608->adpcm[i].flag = 0;
|
||||
F2608->adpcm[i].adpcm_acc = 0;
|
||||
@ -3601,7 +3616,7 @@ void ym2608_reset_chip(void *chip)
|
||||
|
||||
/* DELTA-T unit */
|
||||
DELTAT->freqbase = OPN->ST.freqbase;
|
||||
DELTAT->output_pointer = out_delta;
|
||||
DELTAT->output_pointer = OPN->out_delta;
|
||||
DELTAT->portshift = 5; /* always 5bits shift */ /* ASG */
|
||||
DELTAT->output_range = 1<<23;
|
||||
YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_NORMAL);
|
||||
@ -3713,7 +3728,8 @@ UINT8 ym2608_read(void *chip,int a)
|
||||
int addr = F2608->OPN.ST.address;
|
||||
UINT8 ret = 0;
|
||||
|
||||
switch( a&3 ){
|
||||
switch( a&3 )
|
||||
{
|
||||
case 0: /* status 0 : YM2203 compatible */
|
||||
/* BUSY:x:x:x:x:x:FLAGB:FLAGA */
|
||||
ret = FM_STATUS_FLAG(&F2608->OPN.ST) & 0x83;
|
||||
@ -3800,6 +3816,7 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
int i,j;
|
||||
FMSAMPLE *bufL,*bufR;
|
||||
FM_CH *cch[4];
|
||||
INT32 *out_fm = OPN->out_fm;
|
||||
|
||||
/* buffer setup */
|
||||
bufL = buffer[0];
|
||||
@ -3809,9 +3826,6 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
cch[1] = &F2610->CH[2];
|
||||
cch[2] = &F2610->CH[4];
|
||||
cch[3] = &F2610->CH[5];
|
||||
/* setup adpcm rom address */
|
||||
pcmbufA = F2610->pcmbuf;
|
||||
pcmsizeA = F2610->pcm_size;
|
||||
|
||||
#ifdef YM2610B_WARNING
|
||||
#define FM_KEY_IS(SLOT) ((SLOT)->key)
|
||||
@ -3835,7 +3849,9 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
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, cch[1] );
|
||||
}
|
||||
else
|
||||
refresh_fc_eg_chan( OPN, cch[1] );
|
||||
refresh_fc_eg_chan( OPN, cch[2] );
|
||||
refresh_fc_eg_chan( OPN, cch[3] );
|
||||
|
||||
@ -3846,8 +3862,8 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
advance_lfo(OPN);
|
||||
|
||||
/* clear output acc. */
|
||||
out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
|
||||
out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
|
||||
OPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;
|
||||
OPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;
|
||||
/* clear outputs */
|
||||
out_fm[1] = 0;
|
||||
out_fm[2] = 0;
|
||||
@ -3888,10 +3904,10 @@ void ym2610_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
{
|
||||
int lt,rt;
|
||||
|
||||
lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER];
|
||||
rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
|
||||
lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9;
|
||||
rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9;
|
||||
lt = OPN->out_adpcm[OUTD_LEFT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
rt = OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
lt += (OPN->out_delta[OUTD_LEFT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
rt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
|
||||
|
||||
lt += ((out_fm[1]>>1) & OPN->pan[2]); /* the shift right was verified on real chip */
|
||||
@ -3937,6 +3953,7 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
int i,j;
|
||||
FMSAMPLE *bufL,*bufR;
|
||||
FM_CH *cch[6];
|
||||
INT32 *out_fm = OPN->out_fm;
|
||||
|
||||
/* buffer setup */
|
||||
bufL = buffer[0];
|
||||
@ -3948,9 +3965,6 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
cch[3] = &F2610->CH[3];
|
||||
cch[4] = &F2610->CH[4];
|
||||
cch[5] = &F2610->CH[5];
|
||||
/* setup adpcm rom address */
|
||||
pcmbufA = F2610->pcmbuf;
|
||||
pcmsizeA = F2610->pcm_size;
|
||||
|
||||
/* refresh PG and EG */
|
||||
refresh_fc_eg_chan( OPN, cch[0] );
|
||||
@ -3965,7 +3979,9 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
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, cch[2] );
|
||||
}
|
||||
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] );
|
||||
@ -3977,8 +3993,8 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
advance_lfo(OPN);
|
||||
|
||||
/* clear output acc. */
|
||||
out_adpcm[OUTD_LEFT] = out_adpcm[OUTD_RIGHT]= out_adpcm[OUTD_CENTER] = 0;
|
||||
out_delta[OUTD_LEFT] = out_delta[OUTD_RIGHT]= out_delta[OUTD_CENTER] = 0;
|
||||
OPN->out_adpcm[OUTD_LEFT] = OPN->out_adpcm[OUTD_RIGHT] = OPN->out_adpcm[OUTD_CENTER] = 0;
|
||||
OPN->out_delta[OUTD_LEFT] = OPN->out_delta[OUTD_RIGHT] = OPN->out_delta[OUTD_CENTER] = 0;
|
||||
/* clear outputs */
|
||||
out_fm[0] = 0;
|
||||
out_fm[1] = 0;
|
||||
@ -4025,10 +4041,10 @@ void ym2610b_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
{
|
||||
int lt,rt;
|
||||
|
||||
lt = out_adpcm[OUTD_LEFT] + out_adpcm[OUTD_CENTER];
|
||||
rt = out_adpcm[OUTD_RIGHT] + out_adpcm[OUTD_CENTER];
|
||||
lt += (out_delta[OUTD_LEFT] + out_delta[OUTD_CENTER])>>9;
|
||||
rt += (out_delta[OUTD_RIGHT] + out_delta[OUTD_CENTER])>>9;
|
||||
lt = OPN->out_adpcm[OUTD_LEFT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
rt = OPN->out_adpcm[OUTD_RIGHT] + OPN->out_adpcm[OUTD_CENTER];
|
||||
lt += (OPN->out_delta[OUTD_LEFT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
rt += (OPN->out_delta[OUTD_RIGHT] + OPN->out_delta[OUTD_CENTER])>>9;
|
||||
|
||||
lt += ((out_fm[0]>>1) & OPN->pan[0]); /* the shift right is verified on YM2610 */
|
||||
rt += ((out_fm[0]>>1) & OPN->pan[1]);
|
||||
@ -4255,7 +4271,8 @@ void ym2610_reset_chip(void *chip)
|
||||
}
|
||||
for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
|
||||
/**** ADPCM work initial ****/
|
||||
for( i = 0; i < 6 ; i++ ){
|
||||
for( i = 0; i < 6 ; i++ )
|
||||
{
|
||||
F2610->adpcm[i].step = (UINT32)((float)(1<<ADPCM_SHIFT)*((float)F2610->OPN.ST.freqbase)/3.0);
|
||||
F2610->adpcm[i].now_addr = 0;
|
||||
F2610->adpcm[i].now_step = 0;
|
||||
@ -4263,7 +4280,7 @@ void ym2610_reset_chip(void *chip)
|
||||
F2610->adpcm[i].end = 0;
|
||||
/* F2610->adpcm[i].delta = 21866; */
|
||||
F2610->adpcm[i].vol_mul = 0;
|
||||
F2610->adpcm[i].pan = &out_adpcm[OUTD_CENTER]; /* default center */
|
||||
F2610->adpcm[i].pan = &OPN->out_adpcm[OUTD_CENTER]; /* default center */
|
||||
F2610->adpcm[i].flagMask = 1<<i;
|
||||
F2610->adpcm[i].flag = 0;
|
||||
F2610->adpcm[i].adpcm_acc = 0;
|
||||
@ -4276,7 +4293,7 @@ void ym2610_reset_chip(void *chip)
|
||||
|
||||
/* DELTA-T unit */
|
||||
DELTAT->freqbase = OPN->ST.freqbase;
|
||||
DELTAT->output_pointer = out_delta;
|
||||
DELTAT->output_pointer = OPN->out_delta;
|
||||
DELTAT->portshift = 8; /* allways 8bits shift */
|
||||
DELTAT->output_range = 1<<23;
|
||||
YM_DELTAT_ADPCM_Reset(DELTAT,OUTD_CENTER,YM_DELTAT_EMULATION_MODE_YM2610);
|
||||
@ -4295,7 +4312,8 @@ int ym2610_write(void *chip, int a, UINT8 v)
|
||||
|
||||
v &= 0xff; /* adjust to 8 bit bus */
|
||||
|
||||
switch( a&3 ){
|
||||
switch( a&3 )
|
||||
{
|
||||
case 0: /* address port 0 */
|
||||
OPN->ST.address = v;
|
||||
F2610->addr_A1 = 0;
|
||||
@ -4394,7 +4412,8 @@ UINT8 ym2610_read(void *chip,int a)
|
||||
int addr = F2610->OPN.ST.address;
|
||||
UINT8 ret = 0;
|
||||
|
||||
switch( a&3){
|
||||
switch( a&3)
|
||||
{
|
||||
case 0: /* status 0 : YM2203 compatible */
|
||||
ret = FM_STATUS_FLAG(&F2610->OPN.ST) & 0x83;
|
||||
break;
|
||||
|
@ -670,6 +670,11 @@ typedef struct
|
||||
UINT32 lfo_timer_overflow; /* LFO timer overflows every N samples (depends on LFO frequency) */
|
||||
UINT32 LFO_AM; /* current LFO AM step */
|
||||
UINT32 LFO_PM; /* current LFO PM step */
|
||||
|
||||
INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
INT32 mem; /* one sample delay memory */
|
||||
INT32 out_fm[8]; /* outputs of working channels */
|
||||
|
||||
} FM_OPN;
|
||||
|
||||
/* here's the virtual YM2612 */
|
||||
@ -685,12 +690,6 @@ typedef struct
|
||||
INT32 dacout;
|
||||
} 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 */
|
||||
|
||||
/* log output level */
|
||||
#define LOG_ERR 3 /* ERROR */
|
||||
#define LOG_WAR 2 /* WARNING */
|
||||
@ -1025,9 +1024,9 @@ INLINE void FM_BUSY_SET(FM_ST *ST,int busyclock )
|
||||
|
||||
|
||||
/* set algorithm connection */
|
||||
static void setup_connection( FM_CH *CH, int ch )
|
||||
static void setup_connection( FM_OPN *OPN, FM_CH *CH, int ch )
|
||||
{
|
||||
INT32 *carrier = &out_fm[ch];
|
||||
INT32 *carrier = &OPN->out_fm[ch];
|
||||
|
||||
INT32 **om1 = &CH->connect1;
|
||||
INT32 **om2 = &CH->connect3;
|
||||
@ -1035,46 +1034,47 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
|
||||
INT32 **memc = &CH->mem_connect;
|
||||
|
||||
switch( CH->ALGO ){
|
||||
switch( CH->ALGO )
|
||||
{
|
||||
case 0:
|
||||
/* M1---C1---MEM---M2---C2---OUT */
|
||||
*om1 = &c1;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 1:
|
||||
/* M1------+-MEM---M2---C2---OUT */
|
||||
/* C1-+ */
|
||||
*om1 = &mem;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->mem;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 2:
|
||||
/* M1-----------------+-C2---OUT */
|
||||
/* C1---MEM---M2-+ */
|
||||
*om1 = &c2;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &m2;
|
||||
*om1 = &OPN->c2;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 3:
|
||||
/* M1---C1---MEM------+-C2---OUT */
|
||||
/* M2-+ */
|
||||
*om1 = &c1;
|
||||
*oc1 = &mem;
|
||||
*om2 = &c2;
|
||||
*memc= &c2;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = &OPN->mem;
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->c2;
|
||||
break;
|
||||
case 4:
|
||||
/* M1---C1-+-OUT */
|
||||
/* M2---C2-+ */
|
||||
/* MEM: not used */
|
||||
*om1 = &c1;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = carrier;
|
||||
*om2 = &c2;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*om2 = &OPN->c2;
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
case 5:
|
||||
/* +----C1----+ */
|
||||
@ -1083,17 +1083,17 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
*om1 = 0; /* special mark */
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &m2;
|
||||
*memc= &OPN->m2;
|
||||
break;
|
||||
case 6:
|
||||
/* M1---C1-+ */
|
||||
/* M2-+-OUT */
|
||||
/* C2-+ */
|
||||
/* MEM: not used */
|
||||
*om1 = &c1;
|
||||
*om1 = &OPN->c1;
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
case 7:
|
||||
/* M1-+ */
|
||||
@ -1104,7 +1104,7 @@ static void setup_connection( FM_CH *CH, int ch )
|
||||
*om1 = carrier;
|
||||
*oc1 = carrier;
|
||||
*om2 = carrier;
|
||||
*memc= &mem; /* store it anywhere where it will not be used */
|
||||
*memc= &OPN->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1554,7 +1554,8 @@ INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )
|
||||
/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */
|
||||
static void refresh_fc_eg_chan(FM_OPN *OPN, FM_CH *CH )
|
||||
{
|
||||
if( CH->SLOT[SLOT1].Incr==-1){
|
||||
if( CH->SLOT[SLOT1].Incr==-1)
|
||||
{
|
||||
int fc = CH->fc;
|
||||
int kc = CH->kcode;
|
||||
refresh_fc_eg_slot(OPN, &CH->SLOT[SLOT1] , fc , kc );
|
||||
@ -1592,7 +1593,7 @@ INLINE void chan_calc(YM2612 *F2612, FM_OPN *OPN, FM_CH *CH)
|
||||
{
|
||||
UINT32 AM = OPN->LFO_AM >> CH->ams;
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
OPN->m2 = OPN->c1 = OPN->c2 = OPN->mem = 0;
|
||||
|
||||
*CH->mem_connect = CH->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
|
||||
@ -1601,10 +1602,13 @@ INLINE void chan_calc(YM2612 *F2612, FM_OPN *OPN, FM_CH *CH)
|
||||
INT32 out = CH->op1_out[0] + CH->op1_out[1];
|
||||
CH->op1_out[0] = CH->op1_out[1];
|
||||
|
||||
if( !CH->connect1 ){
|
||||
if( !CH->connect1 )
|
||||
{
|
||||
/* algorithm 5 */
|
||||
mem = c1 = c2 = CH->op1_out[0];
|
||||
}else{
|
||||
OPN->mem = OPN->c1 = OPN->c2 = CH->op1_out[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* other algorithms */
|
||||
*CH->connect1 += CH->op1_out[0];
|
||||
}
|
||||
@ -1622,19 +1626,19 @@ INLINE void chan_calc(YM2612 *F2612, FM_OPN *OPN, FM_CH *CH)
|
||||
|
||||
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, OPN->m2);
|
||||
|
||||
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, OPN->c1);
|
||||
|
||||
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, OPN->c2);
|
||||
|
||||
|
||||
/* store current MEM */
|
||||
CH->mem_value = mem;
|
||||
CH->mem_value = OPN->mem;
|
||||
|
||||
/* update phase counters AFTER output calculations */
|
||||
if(CH->pms)
|
||||
@ -1727,7 +1731,8 @@ static void OPNWriteMode(FM_OPN *OPN, int r, int v)
|
||||
UINT8 c;
|
||||
FM_CH *CH;
|
||||
|
||||
switch(r){
|
||||
switch(r)
|
||||
{
|
||||
case 0x21: /* Test */
|
||||
break;
|
||||
case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */
|
||||
@ -1909,7 +1914,8 @@ static void OPNWriteReg(FM_OPN *OPN, int r, int v)
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
switch( OPN_SLOT(r) ){
|
||||
switch( OPN_SLOT(r) )
|
||||
{
|
||||
case 0: /* 0xa0-0xa2 : FNUM1 */
|
||||
{
|
||||
UINT32 fn = (((UINT32)( (OPN->ST.fn_h)&7))<<8) + v;
|
||||
@ -1949,13 +1955,14 @@ static void OPNWriteReg(FM_OPN *OPN, int r, int v)
|
||||
break;
|
||||
|
||||
case 0xb0:
|
||||
switch( OPN_SLOT(r) ){
|
||||
switch( OPN_SLOT(r) )
|
||||
{
|
||||
case 0: /* 0xb0-0xb2 : FB,ALGO */
|
||||
{
|
||||
int feedback = (v>>3)&7;
|
||||
CH->ALGO = v&7;
|
||||
CH->FB = feedback ? feedback+6 : 0;
|
||||
setup_connection( CH, c );
|
||||
setup_connection( OPN, CH, c );
|
||||
}
|
||||
break;
|
||||
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */
|
||||
@ -2164,16 +2171,15 @@ static void init_tables(void)
|
||||
/*******************************************************************************/
|
||||
/* YM2612 local section */
|
||||
/*******************************************************************************/
|
||||
static int dacen;
|
||||
|
||||
/* Generate samples for one of the YM2612s */
|
||||
void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
{
|
||||
YM2612 *F2612 = (YM2612 *)chip;
|
||||
FM_OPN *OPN = &F2612->OPN;
|
||||
INT32 *out_fm = OPN->out_fm;
|
||||
int i;
|
||||
FMSAMPLE *bufL,*bufR;
|
||||
INT32 dacout = F2612->dacout;
|
||||
FM_CH *cch[6];
|
||||
int lt,rt;
|
||||
|
||||
@ -2187,8 +2193,6 @@ void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
cch[3] = &F2612->CH[3];
|
||||
cch[4] = &F2612->CH[4];
|
||||
cch[5] = &F2612->CH[5];
|
||||
/* DAC mode */
|
||||
dacen = F2612->dacen;
|
||||
|
||||
/* refresh PG and EG */
|
||||
refresh_fc_eg_chan( OPN, cch[0] );
|
||||
@ -2233,8 +2237,8 @@ void ym2612_update_one(void *chip, FMSAMPLE **buffer, int length)
|
||||
chan_calc(F2612, OPN, cch[2]);
|
||||
chan_calc(F2612, OPN, cch[3]);
|
||||
chan_calc(F2612, OPN, cch[4]);
|
||||
if( dacen )
|
||||
*cch[5]->connect4 += dacout;
|
||||
if( F2612->dacen )
|
||||
*cch[5]->connect4 += F2612->dacout;
|
||||
else
|
||||
chan_calc(F2612, OPN, cch[5]);
|
||||
|
||||
@ -2455,7 +2459,8 @@ int ym2612_write(void *chip, int a, UINT8 v)
|
||||
|
||||
v &= 0xff; /* adjust to 8 bit bus */
|
||||
|
||||
switch( a&3){
|
||||
switch( a&3)
|
||||
{
|
||||
case 0: /* address port 0 */
|
||||
F2612->OPN.ST.address = v;
|
||||
F2612->addr_A1 = 0;
|
||||
@ -2515,7 +2520,8 @@ UINT8 ym2612_read(void *chip,int a)
|
||||
{
|
||||
YM2612 *F2612 = (YM2612 *)chip;
|
||||
|
||||
switch( a&3){
|
||||
switch( a&3)
|
||||
{
|
||||
case 0: /* status 0 */
|
||||
return FM_STATUS_FLAG(&F2612->OPN.ST);
|
||||
case 1:
|
||||
|
@ -198,7 +198,8 @@ static FILE * cymfile = NULL;
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ar; /* attack rate: AR<<2 */
|
||||
UINT32 dr; /* decay rate: DR<<2 */
|
||||
UINT32 rr; /* release rate:RR<<2 */
|
||||
@ -238,7 +239,8 @@ typedef struct{
|
||||
UINT16 wavetable;
|
||||
} OPL_SLOT;
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
OPL_SLOT SLOT[2];
|
||||
/* phase generator state */
|
||||
UINT32 block_fnum; /* block+fnum */
|
||||
@ -248,7 +250,8 @@ typedef struct{
|
||||
} OPL_CH;
|
||||
|
||||
/* OPL state */
|
||||
typedef struct fm_opl_f {
|
||||
typedef struct
|
||||
{
|
||||
/* FM channel slots */
|
||||
OPL_CH P_CH[9]; /* OPL/OPL2 chips have 9 channels*/
|
||||
|
||||
@ -262,6 +265,9 @@ typedef struct fm_opl_f {
|
||||
UINT32 fn_tab[1024]; /* fnumber->increment counter */
|
||||
|
||||
/* LFO */
|
||||
UINT32 LFO_AM;
|
||||
INT32 LFO_PM;
|
||||
|
||||
UINT8 lfo_am_depth;
|
||||
UINT8 lfo_pm_depth_range;
|
||||
UINT32 lfo_am_cnt;
|
||||
@ -313,6 +319,12 @@ typedef struct fm_opl_f {
|
||||
double freqbase; /* frequency base */
|
||||
attotime TimerBase; /* Timer base time (==sampling time)*/
|
||||
running_device *device;
|
||||
|
||||
signed int phase_modulation; /* phase modulation input (SLOT 2) */
|
||||
signed int output[1];
|
||||
#if BUILD_Y8950
|
||||
INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
|
||||
#endif
|
||||
} FM_OPL;
|
||||
|
||||
|
||||
@ -627,18 +639,11 @@ static const INT8 lfo_pm_table[8*8*2] = {
|
||||
static int num_lock = 0;
|
||||
|
||||
|
||||
static void *cur_chip = NULL; /* current chip pointer */
|
||||
static OPL_SLOT *SLOT7_1, *SLOT7_2, *SLOT8_1, *SLOT8_2;
|
||||
#define SLOT7_1 (&OPL->P_CH[7].SLOT[SLOT1])
|
||||
#define SLOT7_2 (&OPL->P_CH[7].SLOT[SLOT2])
|
||||
#define SLOT8_1 (&OPL->P_CH[8].SLOT[SLOT1])
|
||||
#define SLOT8_2 (&OPL->P_CH[8].SLOT[SLOT2])
|
||||
|
||||
static signed int phase_modulation; /* phase modulation input (SLOT 2) */
|
||||
static signed int output[1];
|
||||
|
||||
#if BUILD_Y8950
|
||||
static INT32 output_deltat[4]; /* for Y8950 DELTA-T, chip is mono, that 4 here is just for safety */
|
||||
#endif
|
||||
|
||||
static UINT32 LFO_AM;
|
||||
static INT32 LFO_PM;
|
||||
|
||||
|
||||
|
||||
@ -707,12 +712,12 @@ INLINE void advance_lfo(FM_OPL *OPL)
|
||||
tmp = lfo_am_table[ OPL->lfo_am_cnt >> LFO_SH ];
|
||||
|
||||
if (OPL->lfo_am_depth)
|
||||
LFO_AM = tmp;
|
||||
OPL->LFO_AM = tmp;
|
||||
else
|
||||
LFO_AM = tmp>>2;
|
||||
OPL->LFO_AM = tmp>>2;
|
||||
|
||||
OPL->lfo_pm_cnt += OPL->lfo_pm_inc;
|
||||
LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
|
||||
OPL->LFO_PM = ((OPL->lfo_pm_cnt>>LFO_SH) & 7) | OPL->lfo_pm_depth_range;
|
||||
}
|
||||
|
||||
/* advance to next sample */
|
||||
@ -822,7 +827,7 @@ INLINE void advance(FM_OPL *OPL)
|
||||
|
||||
unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
|
||||
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[OPL->LFO_PM + 16*fnum_lfo ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
@ -902,16 +907,16 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign
|
||||
}
|
||||
|
||||
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (OPL->LFO_AM & (OP)->AMmask))
|
||||
|
||||
/* calculate output */
|
||||
INLINE void OPL_CALC_CH( OPL_CH *CH )
|
||||
INLINE void OPL_CALC_CH( FM_OPL *OPL, OPL_CH *CH )
|
||||
{
|
||||
OPL_SLOT *SLOT;
|
||||
unsigned int env;
|
||||
signed int out;
|
||||
|
||||
phase_modulation = 0;
|
||||
OPL->phase_modulation = 0;
|
||||
|
||||
/* SLOT 1 */
|
||||
SLOT = &CH->SLOT[SLOT1];
|
||||
@ -931,7 +936,7 @@ INLINE void OPL_CALC_CH( OPL_CH *CH )
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
|
||||
OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -971,7 +976,7 @@ number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
|
||||
|
||||
/* calculate rhythm */
|
||||
|
||||
INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
INLINE void OPL_CALC_RH( FM_OPL *OPL, OPL_CH *CH, unsigned int noise )
|
||||
{
|
||||
OPL_SLOT *SLOT;
|
||||
signed int out;
|
||||
@ -985,7 +990,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
- output sample always is multiplied by 2
|
||||
*/
|
||||
|
||||
phase_modulation = 0;
|
||||
OPL->phase_modulation = 0;
|
||||
/* SLOT 1 */
|
||||
SLOT = &CH[6].SLOT[SLOT1];
|
||||
env = volume_calc(SLOT);
|
||||
@ -994,7 +999,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
SLOT->op1_out[0] = SLOT->op1_out[1];
|
||||
|
||||
if (!SLOT->CON)
|
||||
phase_modulation = SLOT->op1_out[0];
|
||||
OPL->phase_modulation = SLOT->op1_out[0];
|
||||
/* else ignore output of operator 1 */
|
||||
|
||||
SLOT->op1_out[1] = 0;
|
||||
@ -1009,7 +1014,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
output[0] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
|
||||
OPL->output[0] += op_calc(SLOT->Cnt, env, OPL->phase_modulation, SLOT->wavetable) * 2;
|
||||
|
||||
|
||||
/* Phase generation is based on: */
|
||||
@ -1077,7 +1082,7 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
phase = 0xd0>>2;
|
||||
}
|
||||
|
||||
output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
|
||||
OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
|
||||
}
|
||||
|
||||
/* Snare Drum (verified on real YM3812) */
|
||||
@ -1098,13 +1103,13 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
if (noise)
|
||||
phase ^= 0x100;
|
||||
|
||||
output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
|
||||
OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
|
||||
}
|
||||
|
||||
/* Tom Tom (verified on real YM3812) */
|
||||
env = volume_calc(SLOT8_1);
|
||||
if( env < ENV_QUIET )
|
||||
output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;
|
||||
OPL->output[0] += op_calc(SLOT8_1->Cnt, env, 0, SLOT8_1->wavetable) * 2;
|
||||
|
||||
/* Top Cymbal (verified on real YM3812) */
|
||||
env = volume_calc(SLOT8_2);
|
||||
@ -1131,9 +1136,8 @@ INLINE void OPL_CALC_RH( OPL_CH *CH, unsigned int noise )
|
||||
if (res2)
|
||||
phase = 0x300;
|
||||
|
||||
output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
|
||||
OPL->output[0] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1697,7 +1701,7 @@ static void OPLWriteReg(FM_OPL *OPL, int r, int v)
|
||||
CH = &OPL->P_CH[r&0x0f];
|
||||
CH->SLOT[SLOT1].FB = (v>>1)&7 ? ((v>>1)&7) + 7 : 0;
|
||||
CH->SLOT[SLOT1].CON = v&1;
|
||||
CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &output[0] : &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect1 = CH->SLOT[SLOT1].CON ? &OPL->output[0] : &OPL->phase_modulation;
|
||||
break;
|
||||
case 0xe0: /* waveform select */
|
||||
/* simply ignore write to the waveform select register if selecting not enabled in test register */
|
||||
@ -1729,7 +1733,6 @@ static int OPL_LockTable(running_device *device)
|
||||
|
||||
/* first time */
|
||||
|
||||
cur_chip = NULL;
|
||||
/* allocate total level table (128kb space) */
|
||||
if( !init_tables() )
|
||||
{
|
||||
@ -1756,7 +1759,6 @@ static void OPL_UnLockTable(void)
|
||||
|
||||
/* last time */
|
||||
|
||||
cur_chip = NULL;
|
||||
OPLCloseTable();
|
||||
|
||||
if (cymfile)
|
||||
@ -1801,7 +1803,7 @@ static void OPLResetChip(FM_OPL *OPL)
|
||||
YM_DELTAT *DELTAT = OPL->deltat;
|
||||
|
||||
DELTAT->freqbase = OPL->freqbase;
|
||||
DELTAT->output_pointer = &output_deltat[0];
|
||||
DELTAT->output_pointer = &OPL->output_deltat[0];
|
||||
DELTAT->portshift = 5;
|
||||
DELTAT->output_range = 1<<23;
|
||||
YM_DELTAT_ADPCM_Reset(DELTAT,0,YM_DELTAT_EMULATION_MODE_NORMAL);
|
||||
@ -1854,7 +1856,7 @@ static STATE_POSTLOAD( OPL_postload )
|
||||
SLOT->TLL = SLOT->TL + (CH->ksl_base >> SLOT->ksl);
|
||||
|
||||
/* Connect output */
|
||||
SLOT->connect1 = SLOT->CON ? &output[0] : &phase_modulation;
|
||||
SLOT->connect1 = SLOT->CON ? &OPL->output[0] : &OPL->phase_modulation;
|
||||
}
|
||||
}
|
||||
#if BUILD_Y8950
|
||||
@ -2224,42 +2226,34 @@ void ym3812_update_one(void *chip, OPLSAMPLE *buffer, int length)
|
||||
OPLSAMPLE *buf = buffer;
|
||||
int i;
|
||||
|
||||
if( (void *)OPL != cur_chip ){
|
||||
cur_chip = (void *)OPL;
|
||||
/* rhythm slots */
|
||||
SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
|
||||
}
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
int lt;
|
||||
|
||||
output[0] = 0;
|
||||
OPL->output[0] = 0;
|
||||
|
||||
advance_lfo(OPL);
|
||||
|
||||
/* FM part */
|
||||
OPL_CALC_CH(&OPL->P_CH[0]);
|
||||
OPL_CALC_CH(&OPL->P_CH[1]);
|
||||
OPL_CALC_CH(&OPL->P_CH[2]);
|
||||
OPL_CALC_CH(&OPL->P_CH[3]);
|
||||
OPL_CALC_CH(&OPL->P_CH[4]);
|
||||
OPL_CALC_CH(&OPL->P_CH[5]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[0]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[1]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[2]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[3]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[4]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[5]);
|
||||
|
||||
if(!rhythm)
|
||||
{
|
||||
OPL_CALC_CH(&OPL->P_CH[6]);
|
||||
OPL_CALC_CH(&OPL->P_CH[7]);
|
||||
OPL_CALC_CH(&OPL->P_CH[8]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[6]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[7]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[8]);
|
||||
}
|
||||
else /* Rhythm part */
|
||||
{
|
||||
OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
}
|
||||
|
||||
lt = output[0];
|
||||
lt = OPL->output[0];
|
||||
|
||||
lt >>= FINAL_SH;
|
||||
|
||||
@ -2359,42 +2353,34 @@ void ym3526_update_one(void *chip, OPLSAMPLE *buffer, int length)
|
||||
OPLSAMPLE *buf = buffer;
|
||||
int i;
|
||||
|
||||
if( (void *)OPL != cur_chip ){
|
||||
cur_chip = (void *)OPL;
|
||||
/* rhythm slots */
|
||||
SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
|
||||
}
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
int lt;
|
||||
|
||||
output[0] = 0;
|
||||
OPL->output[0] = 0;
|
||||
|
||||
advance_lfo(OPL);
|
||||
|
||||
/* FM part */
|
||||
OPL_CALC_CH(&OPL->P_CH[0]);
|
||||
OPL_CALC_CH(&OPL->P_CH[1]);
|
||||
OPL_CALC_CH(&OPL->P_CH[2]);
|
||||
OPL_CALC_CH(&OPL->P_CH[3]);
|
||||
OPL_CALC_CH(&OPL->P_CH[4]);
|
||||
OPL_CALC_CH(&OPL->P_CH[5]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[0]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[1]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[2]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[3]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[4]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[5]);
|
||||
|
||||
if(!rhythm)
|
||||
{
|
||||
OPL_CALC_CH(&OPL->P_CH[6]);
|
||||
OPL_CALC_CH(&OPL->P_CH[7]);
|
||||
OPL_CALC_CH(&OPL->P_CH[8]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[6]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[7]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[8]);
|
||||
}
|
||||
else /* Rhythm part */
|
||||
{
|
||||
OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
}
|
||||
|
||||
lt = output[0];
|
||||
lt = OPL->output[0];
|
||||
|
||||
lt >>= FINAL_SH;
|
||||
|
||||
@ -2522,21 +2508,12 @@ void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
|
||||
YM_DELTAT *DELTAT = OPL->deltat;
|
||||
OPLSAMPLE *buf = buffer;
|
||||
|
||||
if( (void *)OPL != cur_chip ){
|
||||
cur_chip = (void *)OPL;
|
||||
/* rhythm slots */
|
||||
SLOT7_1 = &OPL->P_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &OPL->P_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &OPL->P_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &OPL->P_CH[8].SLOT[SLOT2];
|
||||
|
||||
}
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
int lt;
|
||||
|
||||
output[0] = 0;
|
||||
output_deltat[0] = 0;
|
||||
OPL->output[0] = 0;
|
||||
OPL->output_deltat[0] = 0;
|
||||
|
||||
advance_lfo(OPL);
|
||||
|
||||
@ -2545,25 +2522,25 @@ void y8950_update_one(void *chip, OPLSAMPLE *buffer, int length)
|
||||
YM_DELTAT_ADPCM_CALC(DELTAT);
|
||||
|
||||
/* FM part */
|
||||
OPL_CALC_CH(&OPL->P_CH[0]);
|
||||
OPL_CALC_CH(&OPL->P_CH[1]);
|
||||
OPL_CALC_CH(&OPL->P_CH[2]);
|
||||
OPL_CALC_CH(&OPL->P_CH[3]);
|
||||
OPL_CALC_CH(&OPL->P_CH[4]);
|
||||
OPL_CALC_CH(&OPL->P_CH[5]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[0]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[1]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[2]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[3]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[4]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[5]);
|
||||
|
||||
if(!rhythm)
|
||||
{
|
||||
OPL_CALC_CH(&OPL->P_CH[6]);
|
||||
OPL_CALC_CH(&OPL->P_CH[7]);
|
||||
OPL_CALC_CH(&OPL->P_CH[8]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[6]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[7]);
|
||||
OPL_CALC_CH(OPL, &OPL->P_CH[8]);
|
||||
}
|
||||
else /* Rhythm part */
|
||||
{
|
||||
OPL_CALC_RH(&OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
OPL_CALC_RH(OPL, &OPL->P_CH[0], (OPL->noise_rng>>0)&1 );
|
||||
}
|
||||
|
||||
lt = output[0] + (output_deltat[0]>>11);
|
||||
lt = OPL->output[0] + (OPL->output_deltat[0]>>11);
|
||||
|
||||
lt >>= FINAL_SH;
|
||||
|
||||
|
@ -24,7 +24,8 @@ static FILE * cymfile = NULL;
|
||||
|
||||
|
||||
/* struct describing a single operator */
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
UINT32 phase; /* accumulated operator phase */
|
||||
UINT32 freq; /* operator frequency count */
|
||||
INT32 dt1; /* current DT1 (detune 1 phase inc/decrement) value */
|
||||
@ -78,6 +79,10 @@ typedef struct{
|
||||
|
||||
typedef struct
|
||||
{
|
||||
signed int chanout[8];
|
||||
signed int m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
signed int mem; /* one sample delay memory */
|
||||
|
||||
YM2151Operator oper[32]; /* the 32 operators */
|
||||
|
||||
UINT32 pan[16]; /* channels output masks (0xffffffff = enable) */
|
||||
@ -476,12 +481,6 @@ static const UINT8 lfo_noise_waveform[256] = {
|
||||
|
||||
|
||||
|
||||
/* these variables stay here for speedup purposes only */
|
||||
static YM2151 * PSG;
|
||||
static signed int chanout[8];
|
||||
static signed int m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
static signed int mem; /* one sample delay memory */
|
||||
|
||||
|
||||
/* save output as raw 16-bit sample */
|
||||
/* #define SAVE_SAMPLE */
|
||||
@ -752,7 +751,7 @@ static void init_chip_tables(YM2151 *chip)
|
||||
} \
|
||||
}
|
||||
|
||||
INLINE void envelope_KONKOFF(YM2151Operator * op, int v)
|
||||
INLINE void envelope_KONKOFF(YM2151 *PSG, YM2151Operator * op, int v)
|
||||
{
|
||||
if (v&0x08) /* M1 */
|
||||
KEY_ON (op+0, 1)
|
||||
@ -856,7 +855,7 @@ static TIMER_CALLBACK( timer_callback_chip_busy )
|
||||
|
||||
|
||||
|
||||
INLINE void set_connect( YM2151Operator *om1, int cha, int v)
|
||||
INLINE void set_connect(YM2151 *PSG, YM2151Operator *om1, int cha, int v)
|
||||
{
|
||||
YM2151Operator *om2 = om1+1;
|
||||
YM2151Operator *oc1 = om1+2;
|
||||
@ -869,47 +868,47 @@ INLINE void set_connect( YM2151Operator *om1, int cha, int v)
|
||||
{
|
||||
case 0:
|
||||
/* M1---C1---MEM---M2---C2---OUT */
|
||||
om1->connect = &c1;
|
||||
oc1->connect = &mem;
|
||||
om2->connect = &c2;
|
||||
om1->mem_connect = &m2;
|
||||
om1->connect = &PSG->c1;
|
||||
oc1->connect = &PSG->mem;
|
||||
om2->connect = &PSG->c2;
|
||||
om1->mem_connect = &PSG->m2;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* M1------+-MEM---M2---C2---OUT */
|
||||
/* C1-+ */
|
||||
om1->connect = &mem;
|
||||
oc1->connect = &mem;
|
||||
om2->connect = &c2;
|
||||
om1->mem_connect = &m2;
|
||||
om1->connect = &PSG->mem;
|
||||
oc1->connect = &PSG->mem;
|
||||
om2->connect = &PSG->c2;
|
||||
om1->mem_connect = &PSG->m2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
/* M1-----------------+-C2---OUT */
|
||||
/* C1---MEM---M2-+ */
|
||||
om1->connect = &c2;
|
||||
oc1->connect = &mem;
|
||||
om2->connect = &c2;
|
||||
om1->mem_connect = &m2;
|
||||
om1->connect = &PSG->c2;
|
||||
oc1->connect = &PSG->mem;
|
||||
om2->connect = &PSG->c2;
|
||||
om1->mem_connect = &PSG->m2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* M1---C1---MEM------+-C2---OUT */
|
||||
/* M2-+ */
|
||||
om1->connect = &c1;
|
||||
oc1->connect = &mem;
|
||||
om2->connect = &c2;
|
||||
om1->mem_connect = &c2;
|
||||
om1->connect = &PSG->c1;
|
||||
oc1->connect = &PSG->mem;
|
||||
om2->connect = &PSG->c2;
|
||||
om1->mem_connect = &PSG->c2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* M1---C1-+-OUT */
|
||||
/* M2---C2-+ */
|
||||
/* MEM: not used */
|
||||
om1->connect = &c1;
|
||||
oc1->connect = &chanout[cha];
|
||||
om2->connect = &c2;
|
||||
om1->mem_connect = &mem; /* store it anywhere where it will not be used */
|
||||
om1->connect = &PSG->c1;
|
||||
oc1->connect = &PSG->chanout[cha];
|
||||
om2->connect = &PSG->c2;
|
||||
om1->mem_connect = &PSG->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
|
||||
case 5:
|
||||
@ -917,9 +916,9 @@ INLINE void set_connect( YM2151Operator *om1, int cha, int v)
|
||||
/* M1-+-MEM---M2-+-OUT */
|
||||
/* +----C2----+ */
|
||||
om1->connect = 0; /* special mark */
|
||||
oc1->connect = &chanout[cha];
|
||||
om2->connect = &chanout[cha];
|
||||
om1->mem_connect = &m2;
|
||||
oc1->connect = &PSG->chanout[cha];
|
||||
om2->connect = &PSG->chanout[cha];
|
||||
om1->mem_connect = &PSG->m2;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
@ -927,10 +926,10 @@ INLINE void set_connect( YM2151Operator *om1, int cha, int v)
|
||||
/* M2-+-OUT */
|
||||
/* C2-+ */
|
||||
/* MEM: not used */
|
||||
om1->connect = &c1;
|
||||
oc1->connect = &chanout[cha];
|
||||
om2->connect = &chanout[cha];
|
||||
om1->mem_connect = &mem; /* store it anywhere where it will not be used */
|
||||
om1->connect = &PSG->c1;
|
||||
oc1->connect = &PSG->chanout[cha];
|
||||
om2->connect = &PSG->chanout[cha];
|
||||
om1->mem_connect = &PSG->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
|
||||
case 7:
|
||||
@ -939,10 +938,10 @@ INLINE void set_connect( YM2151Operator *om1, int cha, int v)
|
||||
/* M2-+ */
|
||||
/* C2-+ */
|
||||
/* MEM: not used*/
|
||||
om1->connect = &chanout[cha];
|
||||
oc1->connect = &chanout[cha];
|
||||
om2->connect = &chanout[cha];
|
||||
om1->mem_connect = &mem; /* store it anywhere where it will not be used */
|
||||
om1->connect = &PSG->chanout[cha];
|
||||
oc1->connect = &PSG->chanout[cha];
|
||||
om2->connect = &PSG->chanout[cha];
|
||||
om1->mem_connect = &PSG->mem; /* store it anywhere where it will not be used */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1062,7 +1061,8 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
}
|
||||
|
||||
|
||||
switch(r & 0xe0){
|
||||
switch(r & 0xe0)
|
||||
{
|
||||
case 0x00:
|
||||
switch(r){
|
||||
case 0x01: /* LFO reset(bit 1), Test Register (other bits) */
|
||||
@ -1071,8 +1071,7 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
PSG = chip; /* PSG is used in KEY_ON macro */
|
||||
envelope_KONKOFF(&chip->oper[ (v&7)*4 ], v );
|
||||
envelope_KONKOFF(chip, &chip->oper[ (v&7)*4 ], v );
|
||||
break;
|
||||
|
||||
case 0x0f: /* noise mode enable, noise period */
|
||||
@ -1120,7 +1119,8 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (v&0x02){ /* load and start timer B */
|
||||
if (v&0x02)
|
||||
{ /* load and start timer B */
|
||||
#ifdef USE_MAME_TIMERS
|
||||
/* ASG 980324: added a real timer */
|
||||
/* start timer _only_ if it wasn't already started (it will reload time value next round) */
|
||||
@ -1136,7 +1136,9 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
chip->tim_B_val = chip->tim_B_tab[ chip->timer_B_index ];
|
||||
}
|
||||
#endif
|
||||
}else{ /* stop timer B */
|
||||
}
|
||||
else
|
||||
{ /* stop timer B */
|
||||
#ifdef USE_MAME_TIMERS
|
||||
/* ASG 980324: added a real timer */
|
||||
timer_enable(chip->timer_B, 0);
|
||||
@ -1145,7 +1147,8 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (v&0x01){ /* load and start timer A */
|
||||
if (v&0x01)
|
||||
{ /* load and start timer A */
|
||||
#ifdef USE_MAME_TIMERS
|
||||
/* ASG 980324: added a real timer */
|
||||
/* start timer _only_ if it wasn't already started (it will reload time value next round) */
|
||||
@ -1161,7 +1164,9 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
chip->tim_A_val = chip->tim_A_tab[ chip->timer_A_index ];
|
||||
}
|
||||
#endif
|
||||
}else{ /* stop timer A */
|
||||
}
|
||||
else
|
||||
{ /* stop timer A */
|
||||
#ifdef USE_MAME_TIMERS
|
||||
/* ASG 980324: added a real timer */
|
||||
timer_enable(chip->timer_A, 0);
|
||||
@ -1199,13 +1204,14 @@ void ym2151_write_reg(void *_chip, int r, int v)
|
||||
|
||||
case 0x20:
|
||||
op = &chip->oper[ (r&7) * 4 ];
|
||||
switch(r & 0x18){
|
||||
switch(r & 0x18)
|
||||
{
|
||||
case 0x00: /* RL enable, Feedback, Connection */
|
||||
op->fb_shift = ((v>>3)&7) ? ((v>>3)&7)+6:0;
|
||||
chip->pan[ (r&7)*2 ] = (v & 0x40) ? ~0 : 0;
|
||||
chip->pan[ (r&7)*2 +1 ] = (v & 0x80) ? ~0 : 0;
|
||||
chip->connect[r&7] = v&7;
|
||||
set_connect(op, r&7, v&7);
|
||||
set_connect(chip, op, r&7, v&7);
|
||||
break;
|
||||
|
||||
case 0x08: /* Key Code */
|
||||
@ -1382,7 +1388,7 @@ STATE_POSTLOAD( ym2151_postload )
|
||||
int j;
|
||||
|
||||
for (j=0; j<8; j++)
|
||||
set_connect(&YM2151_chip->oper[j*4], j, YM2151_chip->connect[j]);
|
||||
set_connect(YM2151_chip, &YM2151_chip->oper[j*4], j, YM2151_chip->connect[j]);
|
||||
}
|
||||
|
||||
static void ym2151_state_save_register( YM2151 *chip, running_device *device )
|
||||
@ -1680,13 +1686,13 @@ INLINE signed int op_calc1(YM2151Operator * OP, unsigned int env, signed int pm)
|
||||
|
||||
#define volume_calc(OP) ((OP)->tl + ((UINT32)(OP)->volume) + (AM & (OP)->AMmask))
|
||||
|
||||
INLINE void chan_calc(unsigned int chan)
|
||||
INLINE void chan_calc(YM2151 *PSG, unsigned int chan)
|
||||
{
|
||||
YM2151Operator *op;
|
||||
unsigned int env;
|
||||
UINT32 AM = 0;
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
PSG->m2 = PSG->c1 = PSG->c2 = PSG->mem = 0;
|
||||
op = &PSG->oper[chan*4]; /* M1 */
|
||||
|
||||
*op->mem_connect = op->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
@ -1700,7 +1706,7 @@ INLINE void chan_calc(unsigned int chan)
|
||||
|
||||
if (!op->connect)
|
||||
/* algorithm 5 */
|
||||
mem = c1 = c2 = op->fb_out_prev;
|
||||
PSG->mem = PSG->c1 = PSG->c2 = op->fb_out_prev;
|
||||
else
|
||||
/* other algorithms */
|
||||
*op->connect = op->fb_out_prev;
|
||||
@ -1716,26 +1722,27 @@ INLINE void chan_calc(unsigned int chan)
|
||||
|
||||
env = volume_calc(op+1); /* M2 */
|
||||
if (env < ENV_QUIET)
|
||||
*(op+1)->connect += op_calc(op+1, env, m2);
|
||||
*(op+1)->connect += op_calc(op+1, env, PSG->m2);
|
||||
|
||||
env = volume_calc(op+2); /* C1 */
|
||||
if (env < ENV_QUIET)
|
||||
*(op+2)->connect += op_calc(op+2, env, c1);
|
||||
*(op+2)->connect += op_calc(op+2, env, PSG->c1);
|
||||
|
||||
env = volume_calc(op+3); /* C2 */
|
||||
if (env < ENV_QUIET)
|
||||
chanout[chan] += op_calc(op+3, env, c2);
|
||||
PSG->chanout[chan] += op_calc(op+3, env, PSG->c2);
|
||||
|
||||
/* M1 */
|
||||
op->mem_value = mem;
|
||||
op->mem_value = PSG->mem;
|
||||
}
|
||||
INLINE void chan7_calc(void)
|
||||
|
||||
INLINE void chan7_calc(YM2151 *PSG)
|
||||
{
|
||||
YM2151Operator *op;
|
||||
unsigned int env;
|
||||
UINT32 AM = 0;
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
PSG->m2 = PSG->c1 = PSG->c2 = PSG->mem = 0;
|
||||
op = &PSG->oper[7*4]; /* M1 */
|
||||
|
||||
*op->mem_connect = op->mem_value; /* restore delayed sample (MEM) value to m2 or c2 */
|
||||
@ -1749,7 +1756,7 @@ INLINE void chan7_calc(void)
|
||||
|
||||
if (!op->connect)
|
||||
/* algorithm 5 */
|
||||
mem = c1 = c2 = op->fb_out_prev;
|
||||
PSG->mem = PSG->c1 = PSG->c2 = op->fb_out_prev;
|
||||
else
|
||||
/* other algorithms */
|
||||
*op->connect = op->fb_out_prev;
|
||||
@ -1765,11 +1772,11 @@ INLINE void chan7_calc(void)
|
||||
|
||||
env = volume_calc(op+1); /* M2 */
|
||||
if (env < ENV_QUIET)
|
||||
*(op+1)->connect += op_calc(op+1, env, m2);
|
||||
*(op+1)->connect += op_calc(op+1, env, PSG->m2);
|
||||
|
||||
env = volume_calc(op+2); /* C1 */
|
||||
if (env < ENV_QUIET)
|
||||
*(op+2)->connect += op_calc(op+2, env, c1);
|
||||
*(op+2)->connect += op_calc(op+2, env, PSG->c1);
|
||||
|
||||
env = volume_calc(op+3); /* C2 */
|
||||
if (PSG->noise & 0x80)
|
||||
@ -1779,15 +1786,15 @@ INLINE void chan7_calc(void)
|
||||
noiseout = 0;
|
||||
if (env < 0x3ff)
|
||||
noiseout = (env ^ 0x3ff) * 2; /* range of the YM2151 noise output is -2044 to 2040 */
|
||||
chanout[7] += ((PSG->noise_rng&0x10000) ? noiseout: -noiseout); /* bit 16 -> output */
|
||||
PSG->chanout[7] += ((PSG->noise_rng&0x10000) ? noiseout: -noiseout); /* bit 16 -> output */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (env < ENV_QUIET)
|
||||
chanout[7] += op_calc(op+3, env, c2);
|
||||
PSG->chanout[7] += op_calc(op+3, env, PSG->c2);
|
||||
}
|
||||
/* M1 */
|
||||
op->mem_value = mem;
|
||||
op->mem_value = PSG->mem;
|
||||
}
|
||||
|
||||
|
||||
@ -1999,7 +2006,7 @@ rate 11 1 |
|
||||
--
|
||||
*/
|
||||
|
||||
INLINE void advance_eg(void)
|
||||
INLINE void advance_eg(YM2151 *PSG)
|
||||
{
|
||||
YM2151Operator *op;
|
||||
unsigned int i;
|
||||
@ -2083,7 +2090,7 @@ INLINE void advance_eg(void)
|
||||
}
|
||||
|
||||
|
||||
INLINE void advance(void)
|
||||
INLINE void advance(YM2151 *PSG)
|
||||
{
|
||||
YM2151Operator *op;
|
||||
unsigned int i;
|
||||
@ -2123,10 +2130,13 @@ INLINE void advance(void)
|
||||
/* square */
|
||||
/* AM: 255, 0 */
|
||||
/* PM: 128,-128 (LFP = exactly +PMD, -PMD) */
|
||||
if (i<128){
|
||||
if (i<128)
|
||||
{
|
||||
a = 255;
|
||||
p = 128;
|
||||
}else{
|
||||
}
|
||||
else
|
||||
{
|
||||
a = 0;
|
||||
p = -128;
|
||||
}
|
||||
@ -2367,6 +2377,8 @@ INLINE signed int acc_calc(signed int value)
|
||||
*/
|
||||
void ym2151_update_one(void *chip, SAMP **buffers, int length)
|
||||
{
|
||||
YM2151 *PSG = (YM2151 *)chip;
|
||||
signed int *chanout = PSG->chanout;
|
||||
int i;
|
||||
signed int outl,outr;
|
||||
SAMP *bufL, *bufR;
|
||||
@ -2374,8 +2386,6 @@ void ym2151_update_one(void *chip, SAMP **buffers, int length)
|
||||
bufL = buffers[0];
|
||||
bufR = buffers[1];
|
||||
|
||||
PSG = (YM2151 *)chip;
|
||||
|
||||
#ifdef USE_MAME_TIMERS
|
||||
/* ASG 980324 - handled by real timers now */
|
||||
#else
|
||||
@ -2397,7 +2407,7 @@ void ym2151_update_one(void *chip, SAMP **buffers, int length)
|
||||
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
advance_eg();
|
||||
advance_eg(PSG);
|
||||
|
||||
chanout[0] = 0;
|
||||
chanout[1] = 0;
|
||||
@ -2408,21 +2418,21 @@ void ym2151_update_one(void *chip, SAMP **buffers, int length)
|
||||
chanout[6] = 0;
|
||||
chanout[7] = 0;
|
||||
|
||||
chan_calc(0);
|
||||
chan_calc(PSG, 0);
|
||||
SAVE_SINGLE_CHANNEL(0)
|
||||
chan_calc(1);
|
||||
chan_calc(PSG, 1);
|
||||
SAVE_SINGLE_CHANNEL(1)
|
||||
chan_calc(2);
|
||||
chan_calc(PSG, 2);
|
||||
SAVE_SINGLE_CHANNEL(2)
|
||||
chan_calc(3);
|
||||
chan_calc(PSG, 3);
|
||||
SAVE_SINGLE_CHANNEL(3)
|
||||
chan_calc(4);
|
||||
chan_calc(PSG, 4);
|
||||
SAVE_SINGLE_CHANNEL(4)
|
||||
chan_calc(5);
|
||||
chan_calc(PSG, 5);
|
||||
SAVE_SINGLE_CHANNEL(5)
|
||||
chan_calc(6);
|
||||
chan_calc(PSG, 6);
|
||||
SAVE_SINGLE_CHANNEL(6)
|
||||
chan7_calc();
|
||||
chan7_calc(PSG);
|
||||
SAVE_SINGLE_CHANNEL(7)
|
||||
|
||||
outl = chanout[0] & PSG->pan[0];
|
||||
@ -2474,7 +2484,7 @@ void ym2151_update_one(void *chip, SAMP **buffers, int length)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
advance();
|
||||
advance(PSG);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,8 @@ static FILE * cymfile = NULL;
|
||||
|
||||
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ar; /* attack rate: AR<<2 */
|
||||
UINT32 dr; /* decay rate: DR<<2 */
|
||||
UINT32 rr; /* release rate:RR<<2 */
|
||||
@ -208,7 +209,8 @@ typedef struct{
|
||||
unsigned int wavetable;
|
||||
} OPLL_SLOT;
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
OPLL_SLOT SLOT[2];
|
||||
/* phase generator state */
|
||||
UINT32 block_fnum; /* block+fnum */
|
||||
@ -219,7 +221,8 @@ typedef struct{
|
||||
} OPLL_CH;
|
||||
|
||||
/* chip state */
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
OPLL_CH P_CH[9]; /* OPLL chips have 9 channels*/
|
||||
UINT8 instvol_r[9]; /* instrument/volume (or volume/volume in percussive mode)*/
|
||||
|
||||
@ -231,6 +234,8 @@ typedef struct {
|
||||
UINT8 rhythm; /* Rhythm mode */
|
||||
|
||||
/* LFO */
|
||||
UINT32 LFO_AM;
|
||||
INT32 LFO_PM;
|
||||
UINT32 lfo_am_cnt;
|
||||
UINT32 lfo_am_inc;
|
||||
UINT32 lfo_pm_cnt;
|
||||
@ -263,6 +268,10 @@ typedef struct {
|
||||
int rate; /* sampling rate (Hz) */
|
||||
double freqbase; /* frequency base */
|
||||
running_device *device;
|
||||
|
||||
signed int output[2];
|
||||
signed int outchan;
|
||||
|
||||
} YM2413;
|
||||
|
||||
/* key scale level */
|
||||
@ -609,17 +618,14 @@ static const unsigned char table[19][8] = {
|
||||
static int num_lock = 0;
|
||||
|
||||
/* work table */
|
||||
static void *cur_chip = NULL; /* current chip pointer */
|
||||
static OPLL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
|
||||
|
||||
static signed int output[2];
|
||||
static signed int outchan;
|
||||
|
||||
static UINT32 LFO_AM;
|
||||
static INT32 LFO_PM;
|
||||
#define SLOT7_1 (&chip->P_CH[7].SLOT[SLOT1])
|
||||
#define SLOT7_2 (&chip->P_CH[7].SLOT[SLOT2])
|
||||
#define SLOT8_1 (&chip->P_CH[8].SLOT[SLOT1])
|
||||
#define SLOT8_2 (&chip->P_CH[8].SLOT[SLOT2])
|
||||
|
||||
|
||||
INLINE int limit( int val, int max, int min ) {
|
||||
INLINE int limit( int val, int max, int min )
|
||||
{
|
||||
if ( val > max )
|
||||
val = max;
|
||||
else if ( val < min )
|
||||
@ -637,10 +643,10 @@ INLINE void advance_lfo(YM2413 *chip)
|
||||
if (chip->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) ) /* lfo_am_table is 210 elements long */
|
||||
chip->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);
|
||||
|
||||
LFO_AM = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ] >> 1;
|
||||
chip->LFO_AM = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ] >> 1;
|
||||
|
||||
chip->lfo_pm_cnt += chip->lfo_pm_inc;
|
||||
LFO_PM = (chip->lfo_pm_cnt>>LFO_SH) & 7;
|
||||
chip->LFO_PM = (chip->lfo_pm_cnt>>LFO_SH) & 7;
|
||||
}
|
||||
|
||||
/* advance to next sample */
|
||||
@ -817,7 +823,7 @@ INLINE void advance(YM2413 *chip)
|
||||
|
||||
unsigned int fnum_lfo = 8*((CH->block_fnum&0x01c0) >> 6);
|
||||
unsigned int block_fnum = CH->block_fnum * 2;
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + fnum_lfo ];
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[chip->LFO_PM + fnum_lfo ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
@ -904,10 +910,10 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign
|
||||
}
|
||||
|
||||
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (chip->LFO_AM & (OP)->AMmask))
|
||||
|
||||
/* calculate output */
|
||||
INLINE void chan_calc( OPLL_CH *CH )
|
||||
INLINE void chan_calc( YM2413 *chip, OPLL_CH *CH )
|
||||
{
|
||||
OPLL_SLOT *SLOT;
|
||||
unsigned int env;
|
||||
@ -934,16 +940,16 @@ INLINE void chan_calc( OPLL_CH *CH )
|
||||
|
||||
/* SLOT 2 */
|
||||
|
||||
outchan=0;
|
||||
chip->outchan=0;
|
||||
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
{
|
||||
signed int outp = op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);
|
||||
output[0] += outp;
|
||||
outchan = outp;
|
||||
//output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);
|
||||
chip->output[0] += outp;
|
||||
chip->outchan = outp;
|
||||
//chip->output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -984,7 +990,7 @@ number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
|
||||
|
||||
/* calculate rhythm */
|
||||
|
||||
INLINE void rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
INLINE void rhythm_calc( YM2413 *chip, OPLL_CH *CH, unsigned int noise )
|
||||
{
|
||||
OPLL_SLOT *SLOT;
|
||||
signed int out;
|
||||
@ -1021,7 +1027,7 @@ INLINE void rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) * 2;
|
||||
chip->output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) * 2;
|
||||
|
||||
|
||||
/* Phase generation is based on: */
|
||||
@ -1089,7 +1095,7 @@ INLINE void rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
phase = 0xd0>>2;
|
||||
}
|
||||
|
||||
output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
|
||||
chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_1->wavetable) * 2;
|
||||
}
|
||||
|
||||
/* Snare Drum (verified on real YM3812) */
|
||||
@ -1110,13 +1116,13 @@ INLINE void rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
if (noise)
|
||||
phase ^= 0x100;
|
||||
|
||||
output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
|
||||
chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT7_2->wavetable) * 2;
|
||||
}
|
||||
|
||||
/* Tom Tom (verified on real YM3812) */
|
||||
env = volume_calc(SLOT8_1);
|
||||
if( env < ENV_QUIET )
|
||||
output[1] += op_calc(SLOT8_1->phase, env, 0, SLOT8_1->wavetable) * 2;
|
||||
chip->output[1] += op_calc(SLOT8_1->phase, env, 0, SLOT8_1->wavetable) * 2;
|
||||
|
||||
/* Top Cymbal (verified on real YM2413) */
|
||||
env = volume_calc(SLOT8_2);
|
||||
@ -1143,7 +1149,7 @@ INLINE void rhythm_calc( OPLL_CH *CH, unsigned int noise )
|
||||
if (res2)
|
||||
phase = 0x300;
|
||||
|
||||
output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
|
||||
chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, SLOT8_2->wavetable) * 2;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1923,7 +1929,6 @@ static int OPLL_LockTable(running_device *device)
|
||||
|
||||
/* first time */
|
||||
|
||||
cur_chip = NULL;
|
||||
/* allocate total level table (128kb space) */
|
||||
if( !init_tables() )
|
||||
{
|
||||
@ -1950,7 +1955,6 @@ static void OPLL_UnLockTable(void)
|
||||
|
||||
/* last time */
|
||||
|
||||
cur_chip = NULL;
|
||||
OPLCloseTable();
|
||||
|
||||
if (cymfile)
|
||||
@ -2119,47 +2123,37 @@ void ym2413_update_one(void *_chip, SAMP **buffers, int length)
|
||||
|
||||
int i;
|
||||
|
||||
if( (void *)chip != cur_chip ){
|
||||
cur_chip = (void *)chip;
|
||||
/* rhythm slots */
|
||||
SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2];
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
int mo,ro;
|
||||
|
||||
output[0] = 0;
|
||||
output[1] = 0;
|
||||
chip->output[0] = 0;
|
||||
chip->output[1] = 0;
|
||||
|
||||
advance_lfo(chip);
|
||||
|
||||
/* FM part */
|
||||
chan_calc(&chip->P_CH[0]);
|
||||
chan_calc(chip, &chip->P_CH[0]);
|
||||
//SAVE_SEPARATE_CHANNEL(0);
|
||||
chan_calc(&chip->P_CH[1]);
|
||||
chan_calc(&chip->P_CH[2]);
|
||||
chan_calc(&chip->P_CH[3]);
|
||||
chan_calc(&chip->P_CH[4]);
|
||||
chan_calc(&chip->P_CH[5]);
|
||||
chan_calc(chip, &chip->P_CH[1]);
|
||||
chan_calc(chip, &chip->P_CH[2]);
|
||||
chan_calc(chip, &chip->P_CH[3]);
|
||||
chan_calc(chip, &chip->P_CH[4]);
|
||||
chan_calc(chip, &chip->P_CH[5]);
|
||||
|
||||
if(!rhythm)
|
||||
{
|
||||
chan_calc(&chip->P_CH[6]);
|
||||
chan_calc(&chip->P_CH[7]);
|
||||
chan_calc(&chip->P_CH[8]);
|
||||
chan_calc(chip, &chip->P_CH[6]);
|
||||
chan_calc(chip, &chip->P_CH[7]);
|
||||
chan_calc(chip, &chip->P_CH[8]);
|
||||
}
|
||||
else /* Rhythm part */
|
||||
{
|
||||
rhythm_calc(&chip->P_CH[0], (chip->noise_rng>>0)&1 );
|
||||
rhythm_calc(chip, &chip->P_CH[0], (chip->noise_rng>>0)&1 );
|
||||
}
|
||||
|
||||
mo = output[0];
|
||||
ro = output[1];
|
||||
mo = chip->output[0];
|
||||
ro = chip->output[1];
|
||||
|
||||
mo >>= FINAL_SH;
|
||||
ro >>= FINAL_SH;
|
||||
|
@ -141,7 +141,8 @@ static FILE * cymfile = NULL;
|
||||
#define OPL3_TYPE_YMF262 (0) /* 36 operators, 8 waveforms */
|
||||
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
UINT32 ar; /* attack rate: AR<<2 */
|
||||
UINT32 dr; /* decay rate: DR<<2 */
|
||||
UINT32 rr; /* release rate:RR<<2 */
|
||||
@ -191,7 +192,8 @@ unsigned char reserved[128-100];//speedup: pump up the struct size to power of 2
|
||||
|
||||
} OPL3_SLOT;
|
||||
|
||||
typedef struct{
|
||||
typedef struct
|
||||
{
|
||||
OPL3_SLOT SLOT[2];
|
||||
|
||||
UINT32 block_fnum; /* block+fnum */
|
||||
@ -216,12 +218,17 @@ unsigned char reserved[512-272];//speedup:pump up the struct size to power of 2
|
||||
} OPL3_CH;
|
||||
|
||||
/* OPL3 state */
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
OPL3_CH P_CH[18]; /* OPL3 chips have 18 channels */
|
||||
|
||||
UINT32 pan[18*4]; /* channels output masks (0xffffffff = enable); 4 masks per one channel */
|
||||
UINT32 pan_ctrl_value[18]; /* output control values 1 per one channel (1 value contains 4 masks) */
|
||||
|
||||
signed int chanout[18];
|
||||
signed int phase_modulation; /* phase modulation input (SLOT 2) */
|
||||
signed int phase_modulation2; /* phase modulation input (SLOT 3 in 4 operator channels) */
|
||||
|
||||
UINT32 eg_cnt; /* global envelope generator counter */
|
||||
UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/288 (288=8*36) */
|
||||
UINT32 eg_timer_add; /* step of eg_timer */
|
||||
@ -230,6 +237,9 @@ typedef struct {
|
||||
UINT32 fn_tab[1024]; /* fnumber->increment counter */
|
||||
|
||||
/* LFO */
|
||||
UINT32 LFO_AM;
|
||||
INT32 LFO_PM;
|
||||
|
||||
UINT8 lfo_am_depth;
|
||||
UINT8 lfo_pm_depth_range;
|
||||
UINT32 lfo_am_cnt;
|
||||
@ -586,16 +596,12 @@ static const INT8 lfo_pm_table[8*8*2] = {
|
||||
static int num_lock = 0;
|
||||
|
||||
/* work table */
|
||||
static void *cur_chip = NULL; /* current chip point */
|
||||
static OPL3_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
|
||||
|
||||
static signed int phase_modulation; /* phase modulation input (SLOT 2) */
|
||||
static signed int phase_modulation2; /* phase modulation input (SLOT 3 in 4 operator channels) */
|
||||
static signed int chanout[18]; /* 18 channels */
|
||||
#define SLOT7_1 (&chip->P_CH[7].SLOT[SLOT1])
|
||||
#define SLOT7_2 (&chip->P_CH[7].SLOT[SLOT2])
|
||||
#define SLOT8_1 (&chip->P_CH[8].SLOT[SLOT1])
|
||||
#define SLOT8_2 (&chip->P_CH[8].SLOT[SLOT2])
|
||||
|
||||
|
||||
static UINT32 LFO_AM;
|
||||
static INT32 LFO_PM;
|
||||
|
||||
|
||||
|
||||
@ -664,12 +670,12 @@ INLINE void advance_lfo(OPL3 *chip)
|
||||
tmp = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ];
|
||||
|
||||
if (chip->lfo_am_depth)
|
||||
LFO_AM = tmp;
|
||||
chip->LFO_AM = tmp;
|
||||
else
|
||||
LFO_AM = tmp>>2;
|
||||
chip->LFO_AM = tmp>>2;
|
||||
|
||||
chip->lfo_pm_cnt += chip->lfo_pm_inc;
|
||||
LFO_PM = ((chip->lfo_pm_cnt>>LFO_SH) & 7) | chip->lfo_pm_depth_range;
|
||||
chip->LFO_PM = ((chip->lfo_pm_cnt>>LFO_SH) & 7) | chip->lfo_pm_depth_range;
|
||||
}
|
||||
|
||||
/* advance to next sample */
|
||||
@ -784,7 +790,7 @@ INLINE void advance(OPL3 *chip)
|
||||
|
||||
unsigned int fnum_lfo = (block_fnum&0x0380) >> 7;
|
||||
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[LFO_PM + 16*fnum_lfo ];
|
||||
signed int lfo_fn_table_index_offset = lfo_pm_table[chip->LFO_PM + 16*fnum_lfo ];
|
||||
|
||||
if (lfo_fn_table_index_offset) /* LFO phase modulation active */
|
||||
{
|
||||
@ -864,18 +870,18 @@ INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsign
|
||||
}
|
||||
|
||||
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (LFO_AM & (OP)->AMmask))
|
||||
#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (chip->LFO_AM & (OP)->AMmask))
|
||||
|
||||
/* calculate output of a standard 2 operator channel
|
||||
(or 1st part of a 4-op channel) */
|
||||
INLINE void chan_calc( OPL3_CH *CH )
|
||||
INLINE void chan_calc( OPL3 *chip, OPL3_CH *CH )
|
||||
{
|
||||
OPL3_SLOT *SLOT;
|
||||
unsigned int env;
|
||||
signed int out;
|
||||
|
||||
phase_modulation = 0;
|
||||
phase_modulation2= 0;
|
||||
chip->phase_modulation = 0;
|
||||
chip->phase_modulation2= 0;
|
||||
|
||||
/* SLOT 1 */
|
||||
SLOT = &CH->SLOT[SLOT1];
|
||||
@ -896,31 +902,31 @@ INLINE void chan_calc( OPL3_CH *CH )
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable);
|
||||
|
||||
//logerror("out1=%5i vol1=%4i\n", op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable), env );
|
||||
//logerror("out1=%5i vol1=%4i\n", op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable), env );
|
||||
|
||||
}
|
||||
|
||||
/* calculate output of a 2nd part of 4-op channel */
|
||||
INLINE void chan_calc_ext( OPL3_CH *CH )
|
||||
INLINE void chan_calc_ext( OPL3 *chip, OPL3_CH *CH )
|
||||
{
|
||||
OPL3_SLOT *SLOT;
|
||||
unsigned int env;
|
||||
|
||||
phase_modulation = 0;
|
||||
chip->phase_modulation = 0;
|
||||
|
||||
/* SLOT 1 */
|
||||
SLOT = &CH->SLOT[SLOT1];
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation2, SLOT->wavetable );
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation2, SLOT->wavetable );
|
||||
|
||||
/* SLOT 2 */
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable);
|
||||
*SLOT->connect += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable);
|
||||
|
||||
}
|
||||
|
||||
@ -961,9 +967,10 @@ number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
|
||||
|
||||
/* calculate rhythm */
|
||||
|
||||
INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise )
|
||||
INLINE void chan_calc_rhythm( OPL3 *chip, OPL3_CH *CH, unsigned int noise )
|
||||
{
|
||||
OPL3_SLOT *SLOT;
|
||||
signed int *chanout = chip->chanout;
|
||||
signed int out;
|
||||
unsigned int env;
|
||||
|
||||
@ -975,7 +982,7 @@ INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise )
|
||||
- output sample always is multiplied by 2
|
||||
*/
|
||||
|
||||
phase_modulation = 0;
|
||||
chip->phase_modulation = 0;
|
||||
|
||||
/* SLOT 1 */
|
||||
SLOT = &CH[6].SLOT[SLOT1];
|
||||
@ -985,7 +992,7 @@ INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise )
|
||||
SLOT->op1_out[0] = SLOT->op1_out[1];
|
||||
|
||||
if (!SLOT->CON)
|
||||
phase_modulation = SLOT->op1_out[0];
|
||||
chip->phase_modulation = SLOT->op1_out[0];
|
||||
//else ignore output of operator 1
|
||||
|
||||
SLOT->op1_out[1] = 0;
|
||||
@ -1000,7 +1007,7 @@ INLINE void chan_calc_rhythm( OPL3_CH *CH, unsigned int noise )
|
||||
SLOT++;
|
||||
env = volume_calc(SLOT);
|
||||
if( env < ENV_QUIET )
|
||||
chanout[6] += op_calc(SLOT->Cnt, env, phase_modulation, SLOT->wavetable) * 2;
|
||||
chanout[6] += op_calc(SLOT->Cnt, env, chip->phase_modulation, SLOT->wavetable) * 2;
|
||||
|
||||
|
||||
/* Phase generation is based on: */
|
||||
@ -1614,6 +1621,7 @@ static void update_channels(OPL3 *chip, OPL3_CH *CH)
|
||||
static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
{
|
||||
OPL3_CH *CH;
|
||||
signed int *chanout = chip->chanout;
|
||||
unsigned int ch_offset = 0;
|
||||
int slot;
|
||||
int block_fnum;
|
||||
@ -2102,18 +2110,18 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
case 0:
|
||||
/* 1 -> 2 -> 3 -> 4 - out */
|
||||
|
||||
CH->SLOT[SLOT1].connect = &phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
|
||||
break;
|
||||
case 1:
|
||||
/* 1 -> 2 -\
|
||||
3 -> 4 -+- out */
|
||||
|
||||
CH->SLOT[SLOT1].connect = &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
|
||||
(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
|
||||
(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
|
||||
break;
|
||||
case 2:
|
||||
@ -2121,8 +2129,8 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
2 -> 3 -> 4 -+- out */
|
||||
|
||||
CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
|
||||
CH->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
(CH+3)->SLOT[SLOT1].connect = &phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
(CH+3)->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
|
||||
break;
|
||||
case 3:
|
||||
@ -2130,7 +2138,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
2 -> 3 -+- out
|
||||
4 ------/ */
|
||||
CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
|
||||
CH->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
CH->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
(CH+3)->SLOT[SLOT1].connect = &chanout[ chan_no + 3 ];
|
||||
(CH+3)->SLOT[SLOT2].connect = &chanout[ chan_no + 3 ];
|
||||
break;
|
||||
@ -2139,7 +2147,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
else
|
||||
{
|
||||
/* 2 operators mode */
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
|
||||
}
|
||||
break;
|
||||
@ -2154,18 +2162,18 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
case 0:
|
||||
/* 1 -> 2 -> 3 -> 4 - out */
|
||||
|
||||
(CH-3)->SLOT[SLOT1].connect = &phase_modulation;
|
||||
(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
CH->SLOT[SLOT1].connect = &phase_modulation;
|
||||
(CH-3)->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
CH->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
|
||||
break;
|
||||
case 1:
|
||||
/* 1 -> 2 -\
|
||||
3 -> 4 -+- out */
|
||||
|
||||
(CH-3)->SLOT[SLOT1].connect = &phase_modulation;
|
||||
(CH-3)->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
(CH-3)->SLOT[SLOT2].connect = &chanout[ chan_no - 3 ];
|
||||
CH->SLOT[SLOT1].connect = &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
|
||||
break;
|
||||
case 2:
|
||||
@ -2173,8 +2181,8 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
2 -> 3 -> 4 -+- out */
|
||||
|
||||
(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];
|
||||
(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
CH->SLOT[SLOT1].connect = &phase_modulation;
|
||||
(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
CH->SLOT[SLOT1].connect = &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
|
||||
break;
|
||||
case 3:
|
||||
@ -2182,7 +2190,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
2 -> 3 -+- out
|
||||
4 ------/ */
|
||||
(CH-3)->SLOT[SLOT1].connect = &chanout[ chan_no - 3 ];
|
||||
(CH-3)->SLOT[SLOT2].connect = &phase_modulation2;
|
||||
(CH-3)->SLOT[SLOT2].connect = &chip->phase_modulation2;
|
||||
CH->SLOT[SLOT1].connect = &chanout[ chan_no ];
|
||||
CH->SLOT[SLOT2].connect = &chanout[ chan_no ];
|
||||
break;
|
||||
@ -2191,14 +2199,14 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
else
|
||||
{
|
||||
/* 2 operators mode */
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 2 operators mode */
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
|
||||
break;
|
||||
}
|
||||
@ -2206,7 +2214,7 @@ static void OPL3WriteReg(OPL3 *chip, int r, int v)
|
||||
else
|
||||
{
|
||||
/* OPL2 mode - always 2 operators mode */
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &phase_modulation;
|
||||
CH->SLOT[SLOT1].connect = CH->SLOT[SLOT1].CON ? &chanout[(r&0xf)+ch_offset] : &chip->phase_modulation;
|
||||
CH->SLOT[SLOT2].connect = &chanout[(r&0xf)+ch_offset];
|
||||
}
|
||||
break;
|
||||
@ -2250,8 +2258,6 @@ static int OPL3_LockTable(running_device *device)
|
||||
|
||||
/* first time */
|
||||
|
||||
cur_chip = NULL;
|
||||
|
||||
if( !init_tables() )
|
||||
{
|
||||
num_lock--;
|
||||
@ -2276,8 +2282,6 @@ static void OPL3_UnLockTable(void)
|
||||
if(num_lock) return;
|
||||
|
||||
/* last time */
|
||||
|
||||
cur_chip = NULL;
|
||||
OPLCloseTable();
|
||||
|
||||
if (LOG_CYM_FILE)
|
||||
@ -2517,7 +2521,9 @@ void ymf262_set_update_handler(void *chip,OPL3_UPDATEHANDLER UpdateHandler,void
|
||||
*/
|
||||
void ymf262_update_one(void *_chip, OPL3SAMPLE **buffers, int length)
|
||||
{
|
||||
int i;
|
||||
OPL3 *chip = (OPL3 *)_chip;
|
||||
signed int *chanout = chip->chanout;
|
||||
UINT8 rhythm = chip->rhythm&0x20;
|
||||
|
||||
OPL3SAMPLE *ch_a = buffers[0];
|
||||
@ -2525,16 +2531,6 @@ void ymf262_update_one(void *_chip, OPL3SAMPLE **buffers, int length)
|
||||
OPL3SAMPLE *ch_c = buffers[2];
|
||||
OPL3SAMPLE *ch_d = buffers[3];
|
||||
|
||||
int i;
|
||||
|
||||
if( (void *)chip != cur_chip ){
|
||||
cur_chip = (void *)chip;
|
||||
/* rhythm slots */
|
||||
SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1];
|
||||
SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2];
|
||||
SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1];
|
||||
SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2];
|
||||
}
|
||||
for( i=0; i < length ; i++ )
|
||||
{
|
||||
int a,b,c,d;
|
||||
@ -2543,68 +2539,68 @@ void ymf262_update_one(void *_chip, OPL3SAMPLE **buffers, int length)
|
||||
advance_lfo(chip);
|
||||
|
||||
/* clear channel outputs */
|
||||
memset(chanout, 0, sizeof(signed int) * 18);
|
||||
memset(chip->chanout, 0, sizeof(chip->chanout));
|
||||
|
||||
#if 1
|
||||
/* register set #1 */
|
||||
chan_calc(&chip->P_CH[0]); /* extended 4op ch#0 part 1 or 2op ch#0 */
|
||||
chan_calc(chip, &chip->P_CH[0]); /* extended 4op ch#0 part 1 or 2op ch#0 */
|
||||
if (chip->P_CH[0].extended)
|
||||
chan_calc_ext(&chip->P_CH[3]); /* extended 4op ch#0 part 2 */
|
||||
chan_calc_ext(chip, &chip->P_CH[3]); /* extended 4op ch#0 part 2 */
|
||||
else
|
||||
chan_calc(&chip->P_CH[3]); /* standard 2op ch#3 */
|
||||
chan_calc(chip, &chip->P_CH[3]); /* standard 2op ch#3 */
|
||||
|
||||
|
||||
chan_calc(&chip->P_CH[1]); /* extended 4op ch#1 part 1 or 2op ch#1 */
|
||||
chan_calc(chip, &chip->P_CH[1]); /* extended 4op ch#1 part 1 or 2op ch#1 */
|
||||
if (chip->P_CH[1].extended)
|
||||
chan_calc_ext(&chip->P_CH[4]); /* extended 4op ch#1 part 2 */
|
||||
chan_calc_ext(chip, &chip->P_CH[4]); /* extended 4op ch#1 part 2 */
|
||||
else
|
||||
chan_calc(&chip->P_CH[4]); /* standard 2op ch#4 */
|
||||
chan_calc(chip, &chip->P_CH[4]); /* standard 2op ch#4 */
|
||||
|
||||
|
||||
chan_calc(&chip->P_CH[2]); /* extended 4op ch#2 part 1 or 2op ch#2 */
|
||||
chan_calc(chip, &chip->P_CH[2]); /* extended 4op ch#2 part 1 or 2op ch#2 */
|
||||
if (chip->P_CH[2].extended)
|
||||
chan_calc_ext(&chip->P_CH[5]); /* extended 4op ch#2 part 2 */
|
||||
chan_calc_ext(chip, &chip->P_CH[5]); /* extended 4op ch#2 part 2 */
|
||||
else
|
||||
chan_calc(&chip->P_CH[5]); /* standard 2op ch#5 */
|
||||
chan_calc(chip, &chip->P_CH[5]); /* standard 2op ch#5 */
|
||||
|
||||
|
||||
if(!rhythm)
|
||||
{
|
||||
chan_calc(&chip->P_CH[6]);
|
||||
chan_calc(&chip->P_CH[7]);
|
||||
chan_calc(&chip->P_CH[8]);
|
||||
chan_calc(chip, &chip->P_CH[6]);
|
||||
chan_calc(chip, &chip->P_CH[7]);
|
||||
chan_calc(chip, &chip->P_CH[8]);
|
||||
}
|
||||
else /* Rhythm part */
|
||||
{
|
||||
chan_calc_rhythm(&chip->P_CH[0], (chip->noise_rng>>0)&1 );
|
||||
chan_calc_rhythm(chip, &chip->P_CH[0], (chip->noise_rng>>0)&1 );
|
||||
}
|
||||
|
||||
/* register set #2 */
|
||||
chan_calc(&chip->P_CH[ 9]);
|
||||
chan_calc(chip, &chip->P_CH[ 9]);
|
||||
if (chip->P_CH[9].extended)
|
||||
chan_calc_ext(&chip->P_CH[12]);
|
||||
chan_calc_ext(chip, &chip->P_CH[12]);
|
||||
else
|
||||
chan_calc(&chip->P_CH[12]);
|
||||
chan_calc(chip, &chip->P_CH[12]);
|
||||
|
||||
|
||||
chan_calc(&chip->P_CH[10]);
|
||||
chan_calc(chip, &chip->P_CH[10]);
|
||||
if (chip->P_CH[10].extended)
|
||||
chan_calc_ext(&chip->P_CH[13]);
|
||||
chan_calc_ext(chip, &chip->P_CH[13]);
|
||||
else
|
||||
chan_calc(&chip->P_CH[13]);
|
||||
chan_calc(chip, &chip->P_CH[13]);
|
||||
|
||||
|
||||
chan_calc(&chip->P_CH[11]);
|
||||
chan_calc(chip, &chip->P_CH[11]);
|
||||
if (chip->P_CH[11].extended)
|
||||
chan_calc_ext(&chip->P_CH[14]);
|
||||
chan_calc_ext(chip, &chip->P_CH[14]);
|
||||
else
|
||||
chan_calc(&chip->P_CH[14]);
|
||||
chan_calc(chip, &chip->P_CH[14]);
|
||||
|
||||
|
||||
/* channels 15,16,17 are fixed 2-operator channels only */
|
||||
chan_calc(&chip->P_CH[15]);
|
||||
chan_calc(&chip->P_CH[16]);
|
||||
chan_calc(&chip->P_CH[17]);
|
||||
chan_calc(chip, &chip->P_CH[15]);
|
||||
chan_calc(chip, &chip->P_CH[16]);
|
||||
chan_calc(chip, &chip->P_CH[17]);
|
||||
#endif
|
||||
|
||||
/* accumulator register set #1 */
|
||||
|
@ -122,7 +122,6 @@ static const int pcm_tab[] = { 0, 4, 8, -1, 12, 16, 20, -1, 24, 28, 32, -1, 36,
|
||||
static INT16 *wavetable[8];
|
||||
static double plfo_table[4][8][LFO_LENGTH];
|
||||
static int alfo_table[4][LFO_LENGTH];
|
||||
static INT32 *mix;
|
||||
|
||||
#define ENV_ATTACK 0
|
||||
#define ENV_DECAY1 1
|
||||
@ -709,6 +708,7 @@ static STREAM_UPDATE( ymf271_update )
|
||||
int i, j;
|
||||
int op;
|
||||
INT32 *mixp;
|
||||
INT32 mix[48000*2];
|
||||
YMF271Chip *chip = (YMF271Chip *)param;
|
||||
|
||||
memset(mix, 0, sizeof(mix[0])*samples*2);
|
||||
@ -1403,9 +1403,12 @@ static TIMER_CALLBACK( ymf271_timer_b_tick )
|
||||
|
||||
static UINT8 ymf271_read_ext_memory(YMF271Chip *chip, UINT32 address)
|
||||
{
|
||||
if( chip->ext_mem_read.read ) {
|
||||
if( chip->ext_mem_read.read )
|
||||
{
|
||||
return devcb_call_read8(&chip->ext_mem_read, address);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if( address < 0x800000)
|
||||
return chip->rom[address];
|
||||
}
|
||||
@ -1671,8 +1674,6 @@ static void init_tables(running_machine *machine)
|
||||
tri_wave = ((i % (LFO_LENGTH/2)) * ALFO_MAX) / (LFO_LENGTH/2);
|
||||
alfo_table[3][i] = (i < (LFO_LENGTH/2)) ? ALFO_MAX-tri_wave : tri_wave;
|
||||
}
|
||||
|
||||
mix = auto_alloc_array(machine, INT32, 48000*2);
|
||||
}
|
||||
|
||||
static void init_state(YMF271Chip *chip, running_device *device)
|
||||
|
@ -136,8 +136,6 @@ INLINE YMF278BChip *get_safe_token(running_device *device)
|
||||
return (YMF278BChip *)downcast<legacy_device_base *>(device)->token();
|
||||
}
|
||||
|
||||
static INT32 *mix;
|
||||
|
||||
static int ymf278b_compute_rate(YMF278BSlot *slot, int val)
|
||||
{
|
||||
int res, oct;
|
||||
@ -269,6 +267,7 @@ static STREAM_UPDATE( ymf278b_pcm_update )
|
||||
const UINT8 *rombase;
|
||||
INT32 *mixp;
|
||||
INT32 vl, vr;
|
||||
INT32 mix[44100*2];
|
||||
|
||||
memset(mix, 0, sizeof(mix[0])*samples*2);
|
||||
|
||||
@ -672,8 +671,6 @@ static void ymf278b_init(running_device *device, YMF278BChip *chip, void (*cb)(r
|
||||
chip->timer_b = timer_alloc(device->machine, ymf278b_timer_b_tick, chip);
|
||||
chip->irq_line = CLEAR_LINE;
|
||||
chip->clock = device->clock();
|
||||
|
||||
mix = auto_alloc_array(device->machine, INT32, 44100*2);
|
||||
}
|
||||
|
||||
static void ymf278b_register_save_state(running_device *device, YMF278BChip *chip)
|
||||
|
Loading…
Reference in New Issue
Block a user