fm.c
来自「DGen源码最后版本」· C语言 代码 · 共 2,003 行 · 第 1/5 页
C
2,003 行
free(FM2203);
FM2203 = NULL;
}
/* ---------- YM2203 I/O interface ---------- */
int YM2203Write(int n,int a,int v)
{
FM_OPN *OPN = &(FM2203[n].OPN);
if( !(a&1) )
{ /* address port */
OPN->ST.address = v & 0xff;
/* Write register to SSG emurator */
//if( v < 16 ) SSGWrite(n,0,v);
switch(OPN->ST.address)
{
case 0x2d: /* divider sel */
OPNSetPris( OPN, 6*12, 6*12 ,4); /* OPN 1/6 , SSG 1/4 */
break;
case 0x2e: /* divider sel */
OPNSetPris( OPN, 3*12, 3*12,2); /* OPN 1/3 , SSG 1/2 */
break;
case 0x2f: /* divider sel */
OPNSetPris( OPN, 2*12, 2*12,1); /* OPN 1/2 , SSG 1/1 */
break;
}
}
else
{ /* data port */
int addr = OPN->ST.address;
switch( addr & 0xf0 )
{
case 0x00: /* 0x00-0x0f : SSG section */
/* Write data to SSG emurator */
//SSGWrite(n,a,v);
break;
case 0x20: /* 0x20-0x2f : Mode section */
//YM2203UpdateReq(n);
/* write register */
OPNWriteMode(OPN,addr,v);
break;
default: /* 0x30-0xff : OPN section */
//YM2203UpdateReq(n);
/* write register */
OPNWriteReg(OPN,addr,v);
}
}
return OPN->ST.irq;
}
unsigned char YM2203Read(int n,int a)
{
YM2203 *F2203 = &(FM2203[n]);
int addr = F2203->OPN.ST.address;
int ret = 0;
if( !(a&1) )
{ /* status port */
ret = F2203->OPN.ST.status;
}
else
{ /* data port (ONLY SSG) */
//if( addr < 16 ) ret = SSGRead(n);
}
return ret;
}
int YM2203TimerOver(int n,int c)
{
YM2203 *F2203 = &(FM2203[n]);
if( c )
{ /* Timer B */
TimerBOver( &(F2203->OPN.ST) );
}
else
{ /* Timer A */
//YM2203UpdateReq(n);
/* timer update */
TimerAOver( &(F2203->OPN.ST) );
/* CSM mode key,TL controll */
if( F2203->OPN.ST.mode & 0x80 )
{ /* CSM mode total level latch and auto key on */
CSMKeyControll( &(F2203->CH[2]) );
}
}
return F2203->OPN.ST.irq;
}
#endif /* BUILD_YM2203 */
// Dave:
int fm_chan_on=0xffff; // just to make sure :)
#if BUILD_YM2612
/*******************************************************************************/
/* YM2612 local section */
/*******************************************************************************/
static YM2612 *FM2612=NULL; /* array of YM2612's */
/* ---------- update one of chip ----------- */
void YM2612UpdateOne(int num, void **buffer, int length)
{
YM2612 *F2612 = &(FM2612[num]);
FM_OPN *OPN = &(FM2612[num].OPN);
int dataR,dataL;
int i,ch;
int dacen = F2612->dacen;
int dacout = F2612->dacout;
signed short *davel,*daver; // dave
/* set bufer */
bufL = (FMSAMPLE *)buffer[0];
bufR = (FMSAMPLE *)buffer[1];
davel=(signed short *)buffer[0];
daver=(signed short *)buffer[1];
if( (void *)F2612 != cur_chip ){
cur_chip = (void *)F2612;
State = &OPN->ST;
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];
}
/* update frequency counter */
CALC_FCOUNT( cch[0] );
CALC_FCOUNT( cch[1] );
if( (State->mode & 0xc0) ){
/* 3SLOT MODE */
if( cch[2]->SLOT[SLOT1].Incr==-1){
/* 3 slot mode */
CALC_FCSLOT(&cch[2]->SLOT[SLOT1] , OPN->SL3.fc[1] , OPN->SL3.kcode[1] );
CALC_FCSLOT(&cch[2]->SLOT[SLOT2] , OPN->SL3.fc[2] , OPN->SL3.kcode[2] );
CALC_FCSLOT(&cch[2]->SLOT[SLOT3] , OPN->SL3.fc[0] , OPN->SL3.kcode[0] );
CALC_FCSLOT(&cch[2]->SLOT[SLOT4] , cch[2]->fc , cch[2]->kcode );
}
}else CALC_FCOUNT( cch[2] );
CALC_FCOUNT( cch[3] );
CALC_FCOUNT( cch[4] );
CALC_FCOUNT( cch[5] );
/* buffering */
for( i=0; i < length ; i++ )
{
/* clear output acc. */
outd[OPN_LEFT] = outd[OPN_RIGHT]= outd[OPN_CENTER] = 0;
/* calcrate channel output */
// for( ch=0;ch<5;ch++) FM_CALC_CH( cch[ch] );
// Dave:
for( ch=0;ch<5;ch++) if (fm_chan_on&(1<<ch)) FM_CALC_CH( cch[ch] );
dacout=0; // dave temporary
// Dave:
if (fm_chan_on&(1<<5))
{
if( dacen ) *cch[5]->connect4 += dacout;
else FM_CALC_CH( cch[5] );
}
/* get left & right output */
dataL = Limit( outd[OPN_CENTER] + outd[OPN_LEFT], OPN_MAXOUT, OPN_MINOUT );
dataR = Limit( outd[OPN_CENTER] + outd[OPN_RIGHT], OPN_MAXOUT, OPN_MINOUT );
/* buffering */
#ifdef FM_STEREO_MIX /* stereo mixing */
/* stereo mix */
((FMSAMPLE_MIX *)bufL)[i] += ((dataL>>OPN_OUTSB)<<FM_OUTPUT_BIT)|(dataR>>OPN_OUTSB);
#else
/* stereo separate */
{
// Dave - write to signed short and clip
int t;
t=*davel; t+=(dataL*3)>>(OPN_OUTSB+1);
if (t>0x7fff) t=0x7fff; if (t<-0x8000) t=-0x8000;
*davel=t; davel++;
t=*daver; t+=(dataR*3)>>(OPN_OUTSB+1);
if (t>0x7fff) t=0x7fff; if (t<-0x8000) t=-0x8000;
*daver=t; daver++;
}
#endif
#ifdef LFO_SUPPORT
CALC_LOPM_LFO;
#endif
#ifdef INTERNAL_TIMER
/* timer controll */
CALC_TIMER_A( State , cch[2] );
#endif
}
#ifdef INTERNAL_TIMER
CALC_TIMER_B( State , length );
#endif
}
/* -------------------------- YM2612 ---------------------------------- */
int YM2612Init(int num, int clock, int rate,
FM_TIMERHANDLER TimerHandler,FM_IRQHANDLER IRQHandler)
{
int i,j;
if (FM2612) return (-1); /* duplicate init. */
cur_chip = NULL; /* hiro-shi!! */
FMNumChips = num;
/* allocate extend state space */
if( (FM2612 = (YM2612 *)malloc(sizeof(YM2612) * FMNumChips))==NULL)
return (-1);
/* clear */
memset(FM2612,0,sizeof(YM2612) * FMNumChips);
/* allocate total level table (128kb space) */
if( !FMInitTable() )
{
free( FM2612 );
return (-1);
}
for ( i = 0 ; i < FMNumChips; i++ ) {
FM2612[i].OPN.ST.index = i;
FM2612[i].OPN.type = TYPE_YM2612;
FM2612[i].OPN.P_CH = FM2612[i].CH;
FM2612[i].OPN.ST.clock = clock;
// Dave fiddling:
FM2612[i].OPN.ST.rate = rate<<(i-1);
/* FM2612[i].OPN.ST.irq = 0; */
/* FM2612[i].OPN.ST.status = 0; */
FM2612[i].OPN.ST.timermodel = FM_TIMER_SINGLE;
/* Extend handler */
FM2612[i].OPN.ST.Timer_Handler = TimerHandler;
FM2612[i].OPN.ST.IRQ_Handler = IRQHandler;
YM2612ResetChip(i);
}
return 0;
}
/* ---------- shut down emurator ----------- */
void YM2612Shutdown()
{
if (!FM2612) return;
FMCloseTable();
free(FM2612);
FM2612 = NULL;
}
/* ---------- reset one of chip ---------- */
void YM2612ResetChip(int num)
{
int i;
YM2612 *F2612 = &(FM2612[num]);
FM_OPN *OPN = &(FM2612[num].OPN);
OPNSetPris( OPN , 12*12, 12*12, 0);
/* status clear */
FM_IRQMASK_SET(&OPN->ST,0x03);
OPNWriteMode(OPN,0x27,0x30); /* mode 0 , timer reset */
reset_channel( &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 YM2612Write(int n, int a,int v)
{
YM2612 *F2612 = &(FM2612[n]);
int addr;
switch( a&3){
case 0: /* address port 0 */
F2612->OPN.ST.address = v & 0xff;
break;
case 1: /* data port 0 */
addr = F2612->OPN.ST.address;
switch( addr & 0xf0 )
{
case 0x20: /* 0x20-0x2f Mode */
switch( addr )
{
case 0x2a: /* DAC data (YM2612) */
//YM2612UpdateReq(n);
F2612->dacout = v<<(TL_BITS-8);
// {
// extern int mega_dacout;
// mega_dacout=v;
// }
case 0x2b: /* DAC Sel (YM2612) */
/* b7 = dac enable */
F2612->dacen = v & 0x80;
// {
// extern int mega_dacen;
// mega_dacen=v&0x80;
// }
break;
default: /* OPN section */
//YM2612UpdateReq(n);
/* write register */
OPNWriteMode(&(F2612->OPN),addr,v);
}
break;
default: /* 0x30-0xff OPN section */
//YM2612UpdateReq(n);
/* write register */
OPNWriteReg(&(F2612->OPN),addr,v);
}
break;
case 2: /* address port 1 */
F2612->address1 = v & 0xff;
break;
case 3: /* data port 1 */
addr = F2612->address1;
//YM2612UpdateReq(n);
OPNWriteReg(&(F2612->OPN),addr|0x100,v);
break;
}
return F2612->OPN.ST.irq;
}
unsigned char YM2612Read(int n,int a)
{
YM2612 *F2612 = &(FM2612[n]);
int addr = F2612->OPN.ST.address;
switch( a&3){
case 0: /* status 0 */
return F2612->OPN.ST.status;
case 1:
case 2:
case 3:
Log(LOG_WAR,"YM2612 #%d:A=%d read unmapped area\n");
return F2612->OPN.ST.status;
}
return 0;
}
int YM2612TimerOver(int n,int c)
{
YM2612 *F2612 = &(FM2612[n]);
if( c )
{ /* Timer B */
TimerBOver( &(F2612->OPN.ST) );
}
else
{ /* Timer A */
//YM2612UpdateReq(n);
/* 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->CH[2]) );
}
}
return F2612->OPN.ST.irq;
}
#if 0
/* ---------- set buffer ---------- */
int YM2612SetBuffer(int n, FMSAMPLE **buf )
{
int i;
for( i = 0 ; i < YM2612_NUMBUF ; i++){
FM2612[n].Buf[i] = buf[i];
if( cur_chip == &FM2612[n] ) cur_chip = NULL;
}
return 0;
}
#endif
#endif /* BUILD_YM2612 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?