📄 ym2151.c
字号:
chip->noise_f = chip->noise_tab[ v & 0x1f ]; #if 0 if (v){ usrintf_showmessage("YM2151 noise mode = %02x",v); logerror("YM2151 noise (%02x)\n",v); } #endif break; case 0x10: /*timer A hi*/ chip->TimAIndex = (chip->TimAIndex & 0x003) | (v<<2); break; case 0x11: /*timer A low*/ chip->TimAIndex = (chip->TimAIndex & 0x3fc) | (v & 3); break; case 0x12: /*timer B*/ chip->TimBIndex = v; break; case 0x14: /*CSM, irq flag reset, irq enable, timer start/stop*/ chip->IRQenable = v; /*bit 3-timer B, bit 2-timer A, bit 7 - CSM */ if (v&0x20) /*reset timer B irq flag*/ { int oldstate = chip->status & 3; chip->status &= 0xfd; if ((oldstate==2) && (chip->irqhandler)) (*chip->irqhandler)(0); } if (v&0x10) /*reset timer A irq flag*/ { int oldstate = chip->status & 3; chip->status &= 0xfe; if ((oldstate==1) && (chip->irqhandler)) (*chip->irqhandler)(0); } 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)*/ if (!chip->TimBTimer) { chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ], n, timer_callback_b); chip->TimBOldIndex = chip->TimBIndex; } #if 0 else { /*check if timer value has changed since last start and update if necessary*/ if (chip->TimBIndex!=chip->TimBOldIndex) { double timepassed = timer_timeelapsed(chip->TimBTimer); timer_remove (chip->TimBTimer); chip->TimBTimer = timer_set (chip->TimerBTime[ chip->TimBIndex ] - timepassed, n, timer_callback_b); chip->TimBOldIndex = chip->TimBIndex; } } #endif #else if (!chip->TimB) { chip->TimB = 1; chip->TimBVal = chip->TimerB[ chip->TimBIndex ]; } #endif }else{ /*stop timer B*/ #ifdef USE_MAME_TIMERS /* ASG 980324: added a real timer */ if (chip->TimBTimer) timer_remove (chip->TimBTimer); chip->TimBTimer = 0; #else chip->TimB = 0; #endif } 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)*/ if (!chip->TimATimer) { chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ], n, timer_callback_a); chip->TimAOldIndex = chip->TimAIndex; } #if 0 else { /*check if timer value has changed since last start and update if necessary*/ if (chip->TimAIndex!=chip->TimAOldIndex) { double timepassed = timer_timeelapsed(chip->TimATimer); timer_remove (chip->TimATimer); chip->TimATimer = timer_set (chip->TimerATime[ chip->TimAIndex ] - timepassed, n, timer_callback_a); chip->TimAOldIndex = chip->TimAIndex; } } #endif #else if (!chip->TimA) { chip->TimA = 1; chip->TimAVal = chip->TimerA[ chip->TimAIndex ]; } #endif }else{ /*stop timer A*/ #ifdef USE_MAME_TIMERS /* ASG 980324: added a real timer */ if (chip->TimATimer) timer_remove (chip->TimATimer); chip->TimATimer = 0; #else chip->TimA = 0; #endif } break; case 0x18: /*LFO frequency*/ chip->LFOfrq = chip->LFOfreq[ v ]; break; case 0x19: /*PMD (bit 7==1) or AMD (bit 7==0)*/ if (v&0x80) chip->PMD = lfo_md_tab[ v&0x7f ] + 512; else chip->AMD = lfo_md_tab[ v&0x7f ]; break; case 0x1b: /*CT2, CT1, LFO waveform*/ chip->CT = v; chip->LFOwave = (v & 3) * LFO_LEN*2; if (chip->porthandler) (*chip->porthandler)(0 , (chip->CT) >> 6 ); break; default: //logerror("YM2151 Write %02x to undocumented register #%02x\n",v,r); break; } break; case 0x20: op = &chip->Oscils[r & 7]; switch(r & 0x18){ case 0x00: /*RL enable, Feedback, Connection */ op->FeedBack = ((v>>3)&7) ? ((v>>3)&7)+6:0; chip->PAN[ (r&7)*2 ] = (v & 0x40) ? 0xffffffff : 0x0; chip->PAN[ (r&7)*2 +1 ] = (v & 0x80) ? 0xffffffff : 0x0; set_connect(op, v, r&7); break; case 0x08: /*Key Code*/ v &= 0x7f; if ((unsigned int)v != op->KC) { unsigned int kc, kc_channel; kc_channel = (v - (v>>2))*64; kc_channel += 768; kc_channel |= (op->KCindex & 63); (op+ 0)->KC = v; (op+ 0)->KCindex = kc_channel; (op+ 8)->KC = v; (op+ 8)->KCindex = kc_channel; (op+16)->KC = v; (op+16)->KCindex = kc_channel; (op+24)->KC = v; (op+24)->KCindex = kc_channel; kc = v>>2; (op+ 0)->DT1v = chip->DT1freq[ (op+ 0)->DT1 + kc ]; (op+ 0)->freq = ( (chip->freq[ kc_channel + (op+ 0)->DT2 ] + (op+ 0)->DT1v) * (op+ 0)->MUL ) >> 1; (op+ 8)->DT1v = chip->DT1freq[ (op+ 8)->DT1 + kc ]; (op+ 8)->freq = ( (chip->freq[ kc_channel + (op+ 8)->DT2 ] + (op+ 8)->DT1v) * (op+ 8)->MUL ) >> 1; (op+16)->DT1v = chip->DT1freq[ (op+16)->DT1 + kc ]; (op+16)->freq = ( (chip->freq[ kc_channel + (op+16)->DT2 ] + (op+16)->DT1v) * (op+16)->MUL ) >> 1; (op+24)->DT1v = chip->DT1freq[ (op+24)->DT1 + kc ]; (op+24)->freq = ( (chip->freq[ kc_channel + (op+24)->DT2 ] + (op+24)->DT1v) * (op+24)->MUL ) >> 1; refresh_EG( chip, op ); } break; case 0x10: /*Key Fraction*/ v >>= 2; if ((unsigned int)v != (op->KCindex & 63)) { unsigned int kc_channel; kc_channel = v; kc_channel |= (op->KCindex & ~63); (op+ 0)->KCindex = kc_channel; (op+ 8)->KCindex = kc_channel; (op+16)->KCindex = kc_channel; (op+24)->KCindex = kc_channel; (op+ 0)->freq = ( (chip->freq[ kc_channel + (op+ 0)->DT2 ] + (op+ 0)->DT1v) * (op+ 0)->MUL ) >> 1; (op+ 8)->freq = ( (chip->freq[ kc_channel + (op+ 8)->DT2 ] + (op+ 8)->DT1v) * (op+ 8)->MUL ) >> 1; (op+16)->freq = ( (chip->freq[ kc_channel + (op+16)->DT2 ] + (op+16)->DT1v) * (op+16)->MUL ) >> 1; (op+24)->freq = ( (chip->freq[ kc_channel + (op+24)->DT2 ] + (op+24)->DT1v) * (op+24)->MUL ) >> 1; } break; case 0x18: /*PMS,AMS*/ op->PMS = (v>>4) & 7; op->AMS = v & 3; break; } break; case 0x40: /*DT1, MUL*/ { unsigned int oldDT1 = op->DT1; unsigned int oldMUL = op->MUL; op->DT1 = (v&0x70)<<1; op->MUL = (v&0x0f) ? (v&0x0f)<<1: 1; if (oldDT1 != op->DT1) { op->DT1v = chip->DT1freq[ op->DT1 + (op->KC>>2) ]; } if ( (oldDT1 != op->DT1) || (oldMUL != op->MUL) ) { op->freq = ( (chip->freq[ op->KCindex + op->DT2 ] + op->DT1v) * op->MUL ) >> 1; } } break; case 0x60: /*TL*/ op->TL = (v&0x7f)<<(ENV_BITS-7); /*7bit TL*/ break; case 0x80: /*KS, AR*/ { int oldKS = op->KS; int oldAR = op->AR; op->KS = 5-(v>>6); op->AR = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; if ( (op->AR != (unsigned int)oldAR) || (op->KS != (unsigned int)oldKS) ) { if ((op->AR + (op->KC>>op->KS)) < 32+62) op->delta_AR = chip->EG_tab[op->AR + (op->KC>>op->KS) ]; else op->delta_AR = MAX_ATT_INDEX+1; } if (op->KS != (unsigned int)oldKS) { op->delta_D1R = chip->EG_tab[op->D1R + (op->KC>>op->KS) ]; op->delta_D2R = chip->EG_tab[op->D2R + (op->KC>>op->KS) ]; op->delta_RR = chip->EG_tab[op->RR + (op->KC>>op->KS) ]; } } break; case 0xa0: /*AMS-EN, D1R*/ op->AMSmask = (v&0x80) ? 0xffffffff : 0; op->D1R = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; op->delta_D1R = chip->EG_tab[op->D1R + (op->KC>>op->KS) ]; break; case 0xc0: /*DT2, D2R*/ { unsigned int oldDT2 = op->DT2; op->DT2 = DT2_tab[ v>>6 ]; if (op->DT2 != oldDT2) { op->freq = ( (chip->freq[ op->KCindex + op->DT2 ] + op->DT1v) * op->MUL ) >> 1; } } op->D2R = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; op->delta_D2R = chip->EG_tab[op->D2R + (op->KC>>op->KS) ]; break; case 0xe0: /*D1L, RR*/ op->D1L = D1L_tab[ v>>4 ]; op->RR = 34 + ((v&0x0f)<<2); op->delta_RR = chip->EG_tab[op->RR + (op->KC>>op->KS) ]; break; }}#ifdef LOG_CYM_FILEstatic void cymfile_callback (int n){ if (cymfile) { fputc( (unsigned char)0, cymfile ); }}#endifint YM2151ReadStatus( int n ){ return YMPSG[n].status;}/*** Initialize YM2151 emulator(s).**** 'num' is the number of virtual YM2151's to allocate** 'clock' is the chip clock in Hz** 'rate' is sampling rate*/int YM2151Init(int num, int clock, int rate){ int i; if (YMPSG) return (-1); /* duplicate init. */ YMNumChips = num; YMPSG = (YM2151 *)malloc(sizeof(YM2151) * YMNumChips); if (YMPSG == NULL) return (1); memset(YMPSG, 0, sizeof(YM2151) * YMNumChips);#if 0 TL_TAB = (signed int *)malloc(sizeof(signed int) * TL_TAB_LEN ); if (TL_TAB == NULL) { free(YMPSG); YMPSG=NULL; return (1); }#endif init_tables(); for (i=0 ; (unsigned int)i<YMNumChips; i++) { YMPSG[i].clock = clock; /*rate = clock/64;*/ YMPSG[i].sampfreq = rate ? rate : 44100; /* avoid division by 0 in init_chip_tables() */ YMPSG[i].irqhandler = NULL; /*interrupt handler */ YMPSG[i].porthandler = NULL; /*port write handler*/ init_chip_tables(&YMPSG[i]);#ifdef USE_MAME_TIMERS/*this must be done _before_ a call to YM2151ResetChip() */ YMPSG[i].TimATimer = 0; YMPSG[i].TimBTimer = 0;#else YMPSG[i].TimA = 0; YMPSG[i].TimB = 0;#endif YM2151ResetChip(i); /*logerror("YM2151[init] clock=%i sampfreq=%i\n", YMPSG[i].clock, YMPSG[i].sampfreq);*/ }#ifdef LOG_CYM_FILE cymfile = fopen("2151_.cym","wb"); if (cymfile) cymfiletimer = timer_pulse ( TIME_IN_HZ(110), 0, cymfile_callback); /*110 Hz pulse timer*/ else logerror("Could not create file 2151_.cym\n");#endif return(0);}void YM2151Shutdown(){ if (!YMPSG) return; free(YMPSG); YMPSG = NULL;#if 0 if (TL_TAB) { free(TL_TAB); TL_TAB=NULL; }#endif#ifdef LOG_CYM_FILE fclose(cymfile); cymfile = NULL; if (cymfiletimer) timer_remove (cymfiletimer); cymfiletimer = 0;#endif#ifdef SAVE_SAMPLE fclose(sample[8]);#endif#ifdef SAVE_SEPARATE_CHANNELS fclose(sample[0]); fclose(sample[1]); fclose(sample[2]); fclose(sample[3]); fclose(sample[4]); fclose(sample[5]); fclose(sample[6]); fclose(sample[7]);#endif}/*** reset all chip registers.*/void YM2151ResetChip(int num){ int i; YM2151 *chip = &YMPSG[num]; /* initialize hardware registers */ for (i=0; i<32; i++) { memset(&chip->Oscils[i],'\0',sizeof(OscilRec)); chip->Oscils[i].volume = MAX_ATT_INDEX; } chip->LFOphase = 0; chip->LFOfrq = 0; chip->LFOwave = 0; chip->PMD = lfo_md_tab[ 0 ] + 512; chip->AMD = lfo_md_tab[ 0 ]; chip->LFA = 0; chip->LFP = 0; chip->test= 0; chip->IRQenable = 0;#ifdef USE_MAME_TIMERS /* ASG 980324 -- reset the timers before writing to the registers */ if (chip->TimATimer) timer_remove (chip->TimATimer); chip->TimATimer = 0; if (chip->TimBTimer) timer_remove (chip->TimBTimer); chip->TimBTimer = 0;#else chip->TimA = 0; chip->TimB = 0; chip->TimAVal = 0; chip->TimBVal = 0;#endif chip->TimAIndex = 0; chip->TimBIndex = 0; chip->TimAOldIndex = 0; chip->TimBOldIndex = 0; chip->noise = 0; chip->noiseRNG = 0; chip->noise_p = 0; chip->noise_f = chip->noise_tab[0]; chip->CSMreq = 0; chip->status = 0; YM2151WriteReg(num, 0x1b, 0); /*only because of CT1, CT2 output pins*/ for (i=0x20; i<0x100; i++) /*just to set the PM operators */ { YM2151WriteReg(num, i, 0); }}INLINE void lfo_calc(void){unsigned int phase, lfx; if (PSG->test&2) { PSG->LFOphase = 0; phase = PSG->LFOwave; } else { phase = (PSG->LFOphase>>LFO_SH) & LFO_MASK; phase = phase*2 + PSG->LFOwave; } lfx = lfo_tab[phase] + PSG->AMD; PSG->LFA = 0; if (lfx < TL_TAB_LEN) PSG->LFA = TL_TAB[ lfx ]; lfx = lfo_tab[phase+1] + PSG->PMD; PSG->LFP = 0; if (lfx < TL_TAB_LEN) PSG->LFP = TL_TAB[ lfx ];}INLINE void calc_lfo_pm(OscilRec *op){signed int mod_ind, pom; mod_ind = PSG->LFP; /* -128..+127 (8bits signed)*/ if (op->PMS < 6) mod_ind >>= (6 - op->PMS); else mod_ind <<= (op->PMS - 5); if (mod_ind) { unsigned int kc_channel; kc_channel = op->KCindex + mod_ind; pom = ( (PSG->freq[ kc_channel + op->DT2 ] + op->DT1v) * op->MUL ) >> 1; op->phase += (pom - op->freq); op+=8; pom = ( (PSG->freq[ kc_channel + op->DT2 ] + op->DT1v) * op->MUL ) >> 1; op->phase += (pom - op->freq); op+=8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -