static void OPNWriteMode(FM_OPN OPN, int r, int v) { byte c; FM_CH CH; switch (r) { case 0x21: /* Test */ break; #if FM_LFO_SUPPORT case 0x22: /* LFO FREQ (YM2608/YM2612) */ if ((OPN.type & TYPE_LFOPAN) != 0) { OPN.LFOIncr = (v & 0x08) != 0 ? OPN.LFO_FREQ[v & 7] : 0; cur_chip = null; } break; #endif case 0x24: /* timer A High 8*/ OPN.ST.TA = (OPN.ST.TA & 0x03) | (((int)v) << 2); break; case 0x25: /* timer A Low 2*/ OPN.ST.TA = (OPN.ST.TA & 0x3fc) | (v & 3); break; case 0x26: /* timer B */ OPN.ST.TB = (byte)v; break; case 0x27: /* mode , timer controll */ FMSetMode((OPN.ST), OPN.ST.index, v); break; case 0x28: /* key on / off */ c = (byte)(v & 0x03); if (c == 3) break; if ((v & 0x04) != 0 && (OPN.type & TYPE_6CH) != 0) c += 3; CH = OPN.P_CH[c]; //CH = CH[c]; /* csm mode */ if (c == 2 && (OPN.ST.mode & 0x80) != 0) break; if ((v & 0x10) != 0) FM_KEYON(CH, SLOT1); else FM_KEYOFF(CH, SLOT1); if ((v & 0x20) != 0) FM_KEYON(CH, SLOT2); else FM_KEYOFF(CH, SLOT2); if ((v & 0x40) != 0) FM_KEYON(CH, SLOT3); else FM_KEYOFF(CH, SLOT3); if ((v & 0x80) != 0) FM_KEYON(CH, SLOT4); else FM_KEYOFF(CH, SLOT4); /* Log(LOG_INF,"OPN %d:%d : KEY %02X\n",n,c,v&0xf0);*/ break; } }
static void OPNWriteReg(FM_OPN OPN, int r, int v) { byte c; FM_CH CH; FM_SLOT SLOT; /* 0x30 - 0xff */ if( (c = (byte)OPN_CHAN(r)) == 3 ) return; /* 0xX3,0xX7,0xXB,0xXF */ if( (r >= 0x100) /* && (OPN.type & TYPE_6CH) */ ) c+=3; CH = OPN.P_CH[0]; //CH = &CH[c]; SLOT = (CH.SLOT[OPN_SLOT(r)]); switch( r & 0xf0 ) { case 0x30: /* DET , MUL */ set_det_mul(OPN.ST,CH,SLOT,v); break; case 0x40: /* TL */ set_tl(CH,SLOT,v,((c == 2) && (OPN.ST.mode & 0x80) !=0)?1:0); break; case 0x50: /* KS, AR */ set_ar_ksr(CH,SLOT,v,OPN.ST.AR_TABLE); break; case 0x60: /* DR */ /* bit7 = AMS_ON ENABLE(YM2612) */ set_dr(SLOT,v,OPN.ST.DR_TABLE); #if FM_LFO_SUPPORT if( (OPN.type & TYPE_LFOPAN)!=0) { SLOT.amon = (byte)(v>>7); SLOT.ams = CH.ams * SLOT.amon; } #endif break; case 0x70: /* SR */ set_sr(SLOT,v,OPN.ST.DR_TABLE); break; case 0x80: /* SL, RR */ set_sl_rr(SLOT,v,OPN.ST.DR_TABLE); break; case 0x90: /* SSG-EG */ #if !FM_SEG_SUPPORT if((v&0x08)!=0)Mame.printf("OPN %d,%d,%d :SSG-TYPE envelope selected (not supported )\n",OPN.ST.index,c,OPN_SLOT(r)); #endif SLOT.SEG = (byte)(v&0x0f); break; case 0xa0: switch( OPN_SLOT(r) ){ case 0: /* 0xa0-0xa2 : FNUM1 */ { uint fn = (uint)((((uint)( (CH.fn_h)&7))<<8) + v); byte blk = (byte)(CH.fn_h>>3); /* make keyscale code */ CH.kcode = (byte)((blk<<2)|OPN_FKTABLE[(fn>>7)]); /* make basic increment counter 32bit = 1 cycle */ CH.fc = OPN.FN_TABLE[fn]>>(7-blk); CH.SLOT[SLOT1].Incr=unchecked((uint)-1); } break; case 1: /* 0xa4-0xa6 : FNUM2,BLK */ CH.fn_h = (byte)(v&0x3f); break; case 2: /* 0xa8-0xaa : 3CH FNUM1 */ if( r < 0x100) { uint fn = (uint)((((uint)(OPN.SL3.fn_h[c]&7))<<8) + v); byte blk = (byte)(OPN.SL3.fn_h[c]>>3); /* make keyscale code */ OPN.SL3.kcode[c]= (byte)((blk<<2)|OPN_FKTABLE[(fn>>7)]); /* make basic increment counter 32bit = 1 cycle */ OPN.SL3.fc[c] = OPN.FN_TABLE[fn]>>(7-blk); (OPN.P_CH)[2].SLOT[SLOT1].Incr=unchecked((uint)-1); } break; case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ if( r < 0x100) OPN.SL3.fn_h[c] = (byte)(v&0x3f); break; } break; case 0xb0: switch( OPN_SLOT(r) ){ case 0: /* 0xb0-0xb2 : FB,ALGO */ { int feedback = (v>>3)&7; CH.ALGO = (byte)(v&7); CH.FB = (byte)(feedback !=0? 8+1 - feedback : 0); setup_connection( CH ); } break; case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2608) */ if( (OPN.type & TYPE_LFOPAN)!=0) { #if FM_LFO_SUPPORT /* b0-2 PMS */ /* 0,3.4,6.7,10,14,20,40,80(cent) */ double[] pmd_table={0,3.4,6.7,10,14,20,40,80}; int[] amd_table={(int)(0/EG_STEP),(int)(1.4/EG_STEP),(int)((5.9/EG_STEP)),(int)(11.8/EG_STEP) }; CH.pms = (int)((1.5/1200.0)*pmd_table[(v>>4) & 0x07] * PMS_RATE); /* b4-5 AMS */ /* 0 , 1.4 , 5.9 , 11.8(dB) */ CH.ams = (uint)amd_table[(v>>4) & 0x03]; CH.SLOT[SLOT1].ams = CH.ams * CH.SLOT[SLOT1].amon; CH.SLOT[SLOT2].ams = CH.ams * CH.SLOT[SLOT2].amon; CH.SLOT[SLOT3].ams = CH.ams * CH.SLOT[SLOT3].amon; CH.SLOT[SLOT4].ams = CH.ams * CH.SLOT[SLOT4].amon; #endif /* PAN */ CH.PAN = (byte)((v>>6)&0x03); /* PAN : b6 = R , b7 = L */ setup_connection( CH ); /* Log(LOG_INF,"OPN %d,%d : PAN %d\n",n,c,CH.PAN);*/ } break; } break; } }
static void OPNSetPris(FM_OPN OPN, int pris, int TimerPris, int SSGpris) { int i; /* frequency base */ OPN.ST.freqbase = (OPN.ST.rate) != 0 ? ((double)OPN.ST.clock / OPN.ST.rate) / pris : 0; /* Timer base time */ OPN.ST.TimerBase = 1.0 / ((double)OPN.ST.clock / (double)TimerPris); /* SSG part priscaler set */ if (SSGpris != 0) SSGClk(OPN.ST.index, OPN.ST.clock * 2 / SSGpris); /* make time tables */ init_timetables(OPN.ST, OPN_DTTABLE, OPN_ARRATE, OPN_DRRATE); /* make fnumber . increment counter table */ for (i = 0; i < 2048; i++) { /* it is freq table for octave 7 */ /* opn freq counter = 20bit */ OPN.FN_TABLE[i] = (uint)((double)i * OPN.ST.freqbase * FREQ_RATE * (1 << 7) / 2); } #if FM_LFO_SUPPORT /* LFO wave table */ for (i = 0; i < LFO_ENT; i++) { OPN.LFO_wave[i] = i < LFO_ENT / 2 ? i * LFO_RATE / (LFO_ENT / 2) : (LFO_ENT - i) * LFO_RATE / (LFO_ENT / 2); } /* LFO freq. table */ { /* 3.98Hz,5.56Hz,6.02Hz,6.37Hz,6.88Hz,9.63Hz,48.1Hz,72.2Hz @ 8MHz */ double[] freq_table = { 3.98, 5.56, 6.02, 6.37, 6.88, 9.63, 48.1, 72.2 }; for (i = 0; i < 8; i++) { OPN.LFO_FREQ[i] = (uint)((OPN.ST.rate) != 0 ? ((double)LFO_ENT * (1 << LFO_SHIFT) / (OPN.ST.rate / freq_table[i] * (OPN.ST.freqbase * OPN.ST.rate / (8000000.0 / 144)))) : 0); } } #endif /* Log(LOG_INF,"OPN %d set priscaler %d\n",OPN.ST.index,pris);*/ }