YM2612/3834 updates [Eke-Eke, Nemesis]

- Split YM2612/3834 to a separate file to avoid disturbing other OPN chips
- SSG-EG, envelope, LFO, and CSM behavior all improved to better match 
  tested behavior on real YM2612 chips
This commit is contained in:
R. Belmont 2009-08-15 02:48:52 +00:00
parent fd4684ace5
commit 2a76fb52c6
4 changed files with 2656 additions and 544 deletions

1
.gitattributes vendored
View File

@ -819,6 +819,7 @@ src/emu/sound/flt_vol.c svneol=native#text/plain
src/emu/sound/flt_vol.h svneol=native#text/plain
src/emu/sound/fm.c svneol=native#text/plain
src/emu/sound/fm.h svneol=native#text/plain
src/emu/sound/fm2612.c svneol=native#text/plain
src/emu/sound/fmopl.c svneol=native#text/plain
src/emu/sound/fmopl.h svneol=native#text/plain
src/emu/sound/gaelco.c svneol=native#text/plain

View File

@ -132,7 +132,7 @@
#endif
/* shared function building option */
#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B||BUILD_YM2612||BUILD_YM3438)
#define BUILD_OPN (BUILD_YM2203||BUILD_YM2608||BUILD_YM2610||BUILD_YM2610B)
#define BUILD_OPN_PRESCALER (BUILD_YM2203||BUILD_YM2608)
@ -148,7 +148,6 @@
#define TYPE_YM2203 (TYPE_SSG)
#define TYPE_YM2608 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM)
#define TYPE_YM2610 (TYPE_SSG |TYPE_LFOPAN |TYPE_6CH |TYPE_ADPCM |TYPE_2610)
#define TYPE_YM2612 (TYPE_DAC |TYPE_LFOPAN |TYPE_6CH)
@ -292,47 +291,6 @@ O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
};
static const UINT8 eg_rate_select2612[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) from tests on YM2612 */
/* 32 infinite time rates */
O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18),
/* rates 00-11 */
O( 18),O( 18),O( 0),O( 0),
O( 0),O( 0),O( 2),O( 2), // Nemesis's tests
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
O( 0),O( 1),O( 2),O( 3),
/* rate 12 */
O( 4),O( 5),O( 6),O( 7),
/* rate 13 */
O( 8),O( 9),O(10),O(11),
/* rate 14 */
O(12),O(13),O(14),O(15),
/* rate 15 */
O(16),O(16),O(16),O(16),
/* 32 dummy rates (same as 15 3) */
O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16),
O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16)
};
#undef O
/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/
@ -922,26 +880,9 @@ INLINE void FM_KEYON(UINT8 type, FM_CH *CH , int s )
SLOT->key = 1;
SLOT->phase = 0; /* restart Phase Generator */
SLOT->ssgn = (SLOT->ssg & 0x04) >> 1;
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
if( (SLOT->ar + SLOT->ksr) < 32+62 )
{
SLOT->state = EG_ATT; /* phase -> Attack */
}
else
{
/* directly switch to Decay */
SLOT->volume = MIN_ATT_INDEX;
SLOT->state = EG_DEC;
}
}
else
{
SLOT->state = EG_ATT;
}
}
}
INLINE void FM_KEYOFF(FM_CH *CH , int s )
{
@ -1072,16 +1013,8 @@ INLINE void set_ar_ksr(UINT8 type, FM_CH *CH,FM_SLOT *SLOT,int v)
if ((SLOT->ar + SLOT->ksr) < 32+62)
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ];
}
else
{
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
}
}
else
{
SLOT->eg_sh_ar = 0;
@ -1095,32 +1028,17 @@ INLINE void set_dr(UINT8 type, FM_SLOT *SLOT,int v)
SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
SLOT->eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr];
}
else
{
SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
}
}
/* set sustain rate */
INLINE void set_sr(UINT8 type, FM_SLOT *SLOT,int v)
{
SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0;
SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr];
}
else
{
SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
}
}
/* set release rate */
INLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v)
@ -1130,15 +1048,8 @@ INLINE void set_sl_rr(UINT8 type, FM_SLOT *SLOT,int v)
SLOT->rr = 34 + ((v&0x0f)<<2);
SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
if ((type == TYPE_YM2612) || (type == TYPE_YM2608))
{
SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr];
}
else
{
SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
}
}
@ -1238,28 +1149,6 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
break;
case EG_DEC: /* decay phase */
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d1r)-1) ) )
{
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
{
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
}
else
{
SLOT->volume += eg_inc[SLOT->eg_sel_d1r + ((OPN->eg_cnt>>SLOT->eg_sh_d1r)&7)];
}
}
/* check transition even if no volume update: this fixes the case when SL = MIN_ATT_INDEX */
if ( SLOT->volume >= (INT32)(SLOT->sl) )
{
SLOT->volume = (INT32)(SLOT->sl);
SLOT->state = EG_SUS;
}
}
else
{
if (SLOT->ssg&0x08) /* SSG EG type envelope selected */
{
@ -1290,21 +1179,11 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_d2r)-1) ) )
{
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];
}
else
{
SLOT->volume += 4 * eg_inc[SLOT->eg_sel_d2r + ((OPN->eg_cnt>>SLOT->eg_sh_d2r)&7)];
}
if ( SLOT->volume >= ENV_QUIET )
{
if ((OPN->type != TYPE_YM2612) && (OPN->type != TYPE_YM2608))
{
SLOT->volume = MAX_ATT_INDEX;
}
if (SLOT->ssg&0x01) /* bit 0 = hold */
{
@ -1323,20 +1202,6 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
/* restart of the Phase Generator should be here */
SLOT->phase = 0;
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
if ((SLOT->ar + SLOT->ksr) < 94 /*32+62*/)
{
SLOT->state = EG_ATT; /* phase -> Attack */
}
else
{
/* Attack Rate is maximal: directly switch to Decay (or Substain) */
SLOT->volume = MIN_ATT_INDEX;
SLOT->state = (SLOT->sl == MIN_ATT_INDEX) ? EG_SUS : EG_DEC;
}
}
else
{
/* phase -> Attack */
SLOT->volume = 511;
@ -1368,14 +1233,7 @@ static void advance_eg_channel(FM_OPN *OPN, FM_SLOT *SLOT)
if ( !(OPN->eg_cnt & ((1<<SLOT->eg_sh_rr)-1) ) )
{
/* SSG-EG affects Release phase also (Nemesis) */
if ((SLOT->ssg&0x08) && ((OPN->type = TYPE_YM2612) || (OPN->type = TYPE_YM2608)))
{
SLOT->volume += 6 * eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];
}
else
{
SLOT->volume += eg_inc[SLOT->eg_sel_rr + ((OPN->eg_cnt>>SLOT->eg_sh_rr)&7)];
}
if ( SLOT->volume >= MAX_ATT_INDEX )
{
@ -1591,15 +1449,8 @@ INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )
if ((SLOT->ar + SLOT->ksr) < 32+62)
{
SLOT->eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ];
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->eg_sel_ar = eg_rate_select2612[SLOT->ar + SLOT->ksr ];
}
else
{
SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
}
}
else
{
SLOT->eg_sh_ar = 0;
@ -1610,20 +1461,11 @@ INLINE void refresh_fc_eg_slot(FM_OPN *OPN, FM_SLOT *SLOT , int fc , int kc )
SLOT->eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr];
SLOT->eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr];
if ((OPN->type == TYPE_YM2612) || (OPN->type == TYPE_YM2608))
{
SLOT->eg_sel_d1r= eg_rate_select2612[SLOT->d1r + SLOT->ksr];
SLOT->eg_sel_d2r= eg_rate_select2612[SLOT->d2r + SLOT->ksr];
SLOT->eg_sel_rr = eg_rate_select2612[SLOT->rr + SLOT->ksr];
}
else
{
SLOT->eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr];
SLOT->eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr];
SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr];
}
}
}
/* update phase increment counters */
/* Changed from INLINE to static to work around gcc 4.2.1 codegen bug */
@ -4601,375 +4443,3 @@ int ym2610_timer_over(void *chip,int c)
}
#endif /* (BUILD_YM2610||BUILD_YM2610B) */
#if (BUILD_YM2612||BUILD_YM3438)
/*******************************************************************************/
/* YM2612 local section */
/*******************************************************************************/
/* here's the virtual YM2612 */
typedef struct
{
UINT8 REGS[512]; /* registers */
FM_OPN OPN; /* OPN state */
FM_CH CH[6]; /* channel state */
UINT8 addr_A1; /* address line A1 */
/* dac output (YM2612) */
int dacen;
INT32 dacout;
} YM2612;
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;
int i;
FMSAMPLE *bufL,*bufR;
INT32 dacout = F2612->dacout;
FM_CH *cch[6];
/* set bufer */
bufL = buffer[0];
bufR = buffer[1];
cch[0] = &F2612->CH[0];
cch[1] = &F2612->CH[1];
cch[2] = &F2612->CH[2];
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] );
refresh_fc_eg_chan( OPN, cch[1] );
if( (OPN->ST.mode & 0xc0) )
{
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1)
{
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
refresh_fc_eg_slot(OPN, &cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else refresh_fc_eg_chan( OPN, cch[2] );
refresh_fc_eg_chan( OPN, cch[3] );
refresh_fc_eg_chan( OPN, cch[4] );
refresh_fc_eg_chan( OPN, cch[5] );
/* buffering */
for(i=0; i < length ; i++)
{
advance_lfo(OPN);
/* clear outputs */
out_fm[0] = 0;
out_fm[1] = 0;
out_fm[2] = 0;
out_fm[3] = 0;
out_fm[4] = 0;
out_fm[5] = 0;
/* calculate FM */
chan_calc(OPN, cch[0], 0 );
chan_calc(OPN, cch[1], 1 );
chan_calc(OPN, cch[2], 2 );
chan_calc(OPN, cch[3], 3 );
chan_calc(OPN, cch[4], 4 );
if( dacen )
*cch[5]->connect4 += dacout;
else
chan_calc(OPN, cch[5], 5 );
/* advance envelope generator */
OPN->eg_timer += OPN->eg_timer_add;
while (OPN->eg_timer >= OPN->eg_timer_overflow)
{
OPN->eg_timer -= OPN->eg_timer_overflow;
OPN->eg_cnt++;
advance_eg_channel(OPN, &cch[0]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[1]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[2]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[3]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[4]->SLOT[SLOT1]);
advance_eg_channel(OPN, &cch[5]->SLOT[SLOT1]);
}
{
int lt,rt;
lt = ((out_fm[0]>>0) & OPN->pan[0]);
rt = ((out_fm[0]>>0) & OPN->pan[1]);
lt += ((out_fm[1]>>0) & OPN->pan[2]);
rt += ((out_fm[1]>>0) & OPN->pan[3]);
lt += ((out_fm[2]>>0) & OPN->pan[4]);
rt += ((out_fm[2]>>0) & OPN->pan[5]);
lt += ((out_fm[3]>>0) & OPN->pan[6]);
rt += ((out_fm[3]>>0) & OPN->pan[7]);
lt += ((out_fm[4]>>0) & OPN->pan[8]);
rt += ((out_fm[4]>>0) & OPN->pan[9]);
lt += ((out_fm[5]>>0) & OPN->pan[10]);
rt += ((out_fm[5]>>0) & OPN->pan[11]);
lt >>= FINAL_SH;
rt >>= FINAL_SH;
Limit( lt, MAXOUT, MINOUT );
Limit( rt, MAXOUT, MINOUT );
#ifdef SAVE_SAMPLE
SAVE_ALL_CHANNELS
#endif
/* buffering */
bufL[i] = lt;
bufR[i] = rt;
}
/* timer A control */
INTERNAL_TIMER_A( &OPN->ST , cch[2] )
}
INTERNAL_TIMER_B(&OPN->ST,length)
}
#ifdef __STATE_H__
void ym2612_postload(void *chip)
{
if (chip)
{
YM2612 *F2612 = (YM2612 *)chip;
int r;
/* DAC data & port */
F2612->dacout = ((int)F2612->REGS[0x2a] - 0x80) << 6; /* level unknown */
F2612->dacen = F2612->REGS[0x2d] & 0x80;
/* OPN registers */
/* DT / MULTI , TL , KS / AR , AMON / DR , SR , SL / RR , SSG-EG */
for(r=0x30;r<0x9e;r++)
if((r&3) != 3)
{
OPNWriteReg(&F2612->OPN,r,F2612->REGS[r]);
OPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]);
}
/* FB / CONNECT , L / R / AMS / PMS */
for(r=0xb0;r<0xb6;r++)
if((r&3) != 3)
{
OPNWriteReg(&F2612->OPN,r,F2612->REGS[r]);
OPNWriteReg(&F2612->OPN,r|0x100,F2612->REGS[r|0x100]);
}
/* channels */
/*FM_channel_postload(F2612->CH,6);*/
}
}
static void YM2612_save_state(YM2612 *F2612, const device_config *device)
{
state_save_register_device_item_array(device, 0, F2612->REGS);
FMsave_state_st(device,&F2612->OPN.ST);
FMsave_state_channel(device,F2612->CH,6);
/* 3slots */
state_save_register_device_item_array(device, 0, F2612->OPN.SL3.fc);
state_save_register_device_item(device, 0, F2612->OPN.SL3.fn_h);
state_save_register_device_item_array(device, 0, F2612->OPN.SL3.kcode);
/* address register1 */
state_save_register_device_item(device, 0, F2612->addr_A1);
}
#endif /* _STATE_H */
/* initialize YM2612 emulator(s) */
void * ym2612_init(void *param, const device_config *device, int clock, int rate,
FM_TIMERHANDLER timer_handler,FM_IRQHANDLER IRQHandler)
{
YM2612 *F2612;
/* allocate extend state space */
if( (F2612 = (YM2612 *)malloc(sizeof(YM2612)))==NULL)
return NULL;
/* clear */
memset(F2612,0,sizeof(YM2612));
/* allocate total level table (128kb space) */
if( !init_tables() )
{
free( F2612 );
return NULL;
}
F2612->OPN.ST.param = param;
F2612->OPN.type = TYPE_YM2612;
F2612->OPN.P_CH = F2612->CH;
F2612->OPN.ST.device = device;
F2612->OPN.ST.clock = clock;
F2612->OPN.ST.rate = rate;
/* F2612->OPN.ST.irq = 0; */
/* F2612->OPN.ST.status = 0; */
/* Extend handler */
F2612->OPN.ST.timer_handler = timer_handler;
F2612->OPN.ST.IRQ_Handler = IRQHandler;
#ifdef __STATE_H__
YM2612_save_state(F2612, device);
#endif
return F2612;
}
/* shut down emulator */
void ym2612_shutdown(void *chip)
{
YM2612 *F2612 = (YM2612 *)chip;
FMCloseTable();
free(F2612);
}
/* reset one of chip */
void ym2612_reset_chip(void *chip)
{
int i;
YM2612 *F2612 = (YM2612 *)chip;
FM_OPN *OPN = &F2612->OPN;
OPNSetPres( OPN, 6*24, 6*24, 0);
/* status clear */
FM_IRQMASK_SET(&OPN->ST,0x03);
FM_BUSY_CLEAR(&OPN->ST);
OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
OPN->eg_timer = 0;
OPN->eg_cnt = 0;
FM_STATUS_RESET(&OPN->ST, 0xff);
reset_channels( &OPN->ST , &F2612->CH[0] , 6 );
for(i = 0xb6 ; i >= 0xb4 ; i-- )
{
OPNWriteReg(OPN,i ,0xc0);
OPNWriteReg(OPN,i|0x100,0xc0);
}
for(i = 0xb2 ; i >= 0x30 ; i-- )
{
OPNWriteReg(OPN,i ,0);
OPNWriteReg(OPN,i|0x100,0);
}
for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(OPN,i,0);
/* DAC mode clear */
F2612->dacen = 0;
}
/* YM2612 write */
/* n = number */
/* a = address */
/* v = value */
int ym2612_write(void *chip, int a, UINT8 v)
{
YM2612 *F2612 = (YM2612 *)chip;
int addr;
v &= 0xff; /* adjust to 8 bit bus */
switch( a&3){
case 0: /* address port 0 */
F2612->OPN.ST.address = v;
F2612->addr_A1 = 0;
break;
case 1: /* data port 0 */
if (F2612->addr_A1 != 0)
break; /* verified on real YM2608 */
addr = F2612->OPN.ST.address;
F2612->REGS[addr] = v;
switch( addr & 0xf0 )
{
case 0x20: /* 0x20-0x2f Mode */
switch( addr )
{
case 0x2a: /* DAC data (YM2612) */
ym2612_update_req(F2612->OPN.ST.param);
F2612->dacout = ((int)v - 0x80) << 6; /* level unknown */
break;
case 0x2b: /* DAC Sel (YM2612) */
/* b7 = dac enable */
F2612->dacen = v & 0x80;
break;
default: /* OPN section */
ym2612_update_req(F2612->OPN.ST.param);
/* write register */
OPNWriteMode(&(F2612->OPN),addr,v);
}
break;
default: /* 0x30-0xff OPN section */
ym2612_update_req(F2612->OPN.ST.param);
/* write register */
OPNWriteReg(&(F2612->OPN),addr,v);
}
break;
case 2: /* address port 1 */
F2612->OPN.ST.address = v;
F2612->addr_A1 = 1;
break;
case 3: /* data port 1 */
if (F2612->addr_A1 != 1)
break; /* verified on real YM2608 */
addr = F2612->OPN.ST.address;
F2612->REGS[addr | 0x100] = v;
ym2612_update_req(F2612->OPN.ST.param);
OPNWriteReg(&(F2612->OPN),addr | 0x100,v);
break;
}
return F2612->OPN.ST.irq;
}
UINT8 ym2612_read(void *chip,int a)
{
YM2612 *F2612 = (YM2612 *)chip;
switch( a&3){
case 0: /* status 0 */
return FM_STATUS_FLAG(&F2612->OPN.ST);
case 1:
case 2:
case 3:
LOG(LOG_WAR,("YM2612 #%p:A=%d read unmapped area\n",F2612->OPN.ST.param,a));
return FM_STATUS_FLAG(&F2612->OPN.ST);
}
return 0;
}
int ym2612_timer_over(void *chip,int c)
{
YM2612 *F2612 = (YM2612 *)chip;
if( c )
{ /* Timer B */
TimerBOver( &(F2612->OPN.ST) );
}
else
{ /* Timer A */
ym2612_update_req(F2612->OPN.ST.param);
/* timer update */
TimerAOver( &(F2612->OPN.ST) );
/* CSM mode key,TL controll */
if( F2612->OPN.ST.mode & 0x80 )
{ /* CSM mode total level latch and auto key on */
CSMKeyControll( F2612->OPN.type, &(F2612->CH[2]) );
}
}
return F2612->OPN.ST.irq;
}
#endif /* (BUILD_YM2612||BUILD_YM3238) */

2641
src/emu/sound/fm2612.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -729,7 +729,7 @@ SOUNDOBJS += $(SOUNDOBJ)/2610intf.o $(SOUNDOBJ)/ay8910.o $(SOUNDOBJ)/fm.o $(SOUN
endif
ifneq ($(filter YM2612 YM3438,$(SOUNDS)),)
SOUNDOBJS += $(SOUNDOBJ)/2612intf.o $(SOUNDOBJ)/ay8910.o $(SOUNDOBJ)/fm.o
SOUNDOBJS += $(SOUNDOBJ)/2612intf.o $(SOUNDOBJ)/ay8910.o $(SOUNDOBJ)/fm2612.o
endif
ifneq ($(filter YM3812,$(SOUNDS)),)