public static void InitAndReset(int apuIdx, int sampleRate, bool pal, int expansion, int numExpansionChannels, [MarshalAs(UnmanagedType.FunctionPtr)] DmcReadDelegate dmcCallback) { Init(apuIdx, sampleRate, pal ? 1 : 0, expansion, dmcCallback); Reset(apuIdx); WriteRegister(apuIdx, APU_SND_CHN, 0x0f); // enable channels, stop DMC WriteRegister(apuIdx, APU_TRI_LINEAR, 0x80); // disable triangle length counter WriteRegister(apuIdx, APU_NOISE_HI, 0x00); // load noise length WriteRegister(apuIdx, APU_PL1_VOL, 0x30); // volumes to 0 WriteRegister(apuIdx, APU_PL2_VOL, 0x30); WriteRegister(apuIdx, APU_NOISE_VOL, 0x30); WriteRegister(apuIdx, APU_PL1_SWEEP, 0x08); // no sweep WriteRegister(apuIdx, APU_PL2_SWEEP, 0x08); var apuSettings = Settings.ExpansionMixerSettings[NesApu.APU_EXPANSION_NONE]; var expSettings = Settings.ExpansionMixerSettings[expansion]; TrebleEq(apuIdx, NesApu.APU_EXPANSION_NONE, apuSettings.treble, sampleRate); SetExpansionVolume(apuIdx, NesApu.APU_EXPANSION_NONE, Utils.DbToAmplitude(apuSettings.volume)); if (expansion != APU_EXPANSION_NONE) { TrebleEq(apuIdx, expansion, expSettings.treble, sampleRate); SetExpansionVolume(apuIdx, expansion, Utils.DbToAmplitude(expSettings.volume)); } switch (expansion) { case APU_EXPANSION_VRC6: WriteRegister(apuIdx, VRC6_CTRL, 0x00); // No halt, no octave change break; case APU_EXPANSION_FDS: break; case APU_EXPANSION_MMC5: WriteRegister(apuIdx, MMC5_PL1_VOL, 0x10); WriteRegister(apuIdx, MMC5_PL2_VOL, 0x10); WriteRegister(apuIdx, MMC5_SND_CHN, 0x03); // Enable both square channels. break; case APU_EXPANSION_VRC7: WriteRegister(apuIdx, VRC7_SILENCE, 0x00); // Enable VRC7 audio. break; case APU_EXPANSION_NAMCO: // This is mainly because the instrument player might not update all the channels all the time. WriteRegister(apuIdx, N163_ADDR, N163_REG_VOLUME); WriteRegister(apuIdx, N163_DATA, (numExpansionChannels - 1) << 4); break; case APU_EXPANSION_SUNSOFT: WriteRegister(apuIdx, S5B_ADDR, S5B_REG_TONE); WriteRegister(apuIdx, S5B_DATA, 0x38); // No noise, just 3 tones for now. break; } }
public static void InitAndReset(int apuIdx, int sampleRate, bool pal, int seperateTndMode, int expansions, int numNamcoChannels, [MarshalAs(UnmanagedType.FunctionPtr)] DmcReadDelegate dmcCallback) { Init(apuIdx, sampleRate, pal ? 1 : 0, seperateTndMode, expansions, dmcCallback); Reset(apuIdx); WriteRegister(apuIdx, APU_SND_CHN, 0x0f); // enable channels, stop DMC WriteRegister(apuIdx, APU_TRI_LINEAR, 0x80); // disable triangle length counter WriteRegister(apuIdx, APU_NOISE_HI, 0x00); // load noise length WriteRegister(apuIdx, APU_PL1_VOL, 0x30); // volumes to 0 WriteRegister(apuIdx, APU_PL2_VOL, 0x30); WriteRegister(apuIdx, APU_NOISE_VOL, 0x30); WriteRegister(apuIdx, APU_PL1_SWEEP, 0x08); // no sweep WriteRegister(apuIdx, APU_PL2_SWEEP, 0x08); var apuSettings = Settings.ExpansionMixerSettings[NesApu.APU_EXPANSION_NONE]; TrebleEq(apuIdx, NesApu.APU_EXPANSION_NONE, apuSettings.treble, sampleRate); SetExpansionVolume(apuIdx, NesApu.APU_EXPANSION_NONE, Utils.DbToAmplitude(apuSettings.volume + Settings.GlobalVolume)); if (expansions != APU_EXPANSION_MASK_NONE) { for (int expansion = APU_EXPANSION_FIRST; expansion <= APU_EXPANSION_LAST; expansion++) { if ((expansions & ExpansionToMask(expansion)) != 0) { var expSettings = Settings.ExpansionMixerSettings[expansion]; TrebleEq(apuIdx, expansion, expSettings.treble, sampleRate); SetExpansionVolume(apuIdx, expansion, Utils.DbToAmplitude(expSettings.volume + Settings.GlobalVolume)); switch (expansion) { case APU_EXPANSION_VRC6: WriteRegister(apuIdx, VRC6_CTRL, 0x00); // No halt, no octave change break; case APU_EXPANSION_FDS: break; case APU_EXPANSION_MMC5: WriteRegister(apuIdx, MMC5_PL1_VOL, 0x10); WriteRegister(apuIdx, MMC5_PL2_VOL, 0x10); WriteRegister(apuIdx, MMC5_SND_CHN, 0x03); // Enable both square channels. break; case APU_EXPANSION_VRC7: // HACK : There is a conflict between the VRC7 silence register and S5B data register, a write to // the silence register (E000) will be interpreted as a S5B data write. To prevent this, we // select a dummy register for S5B so that the write is discarded. if ((expansions & APU_EXPANSION_MASK_SUNSOFT) != 0) { WriteRegister(apuIdx, S5B_ADDR, S5B_REG_IO_A); } WriteRegister(apuIdx, VRC7_SILENCE, 0x00); // Enable VRC7 audio. break; case APU_EXPANSION_NAMCO: // This is mainly because the instrument player might not update all the channels all the time. WriteRegister(apuIdx, N163_ADDR, N163_REG_VOLUME); WriteRegister(apuIdx, N163_DATA, (numNamcoChannels - 1) << 4); break; case APU_EXPANSION_SUNSOFT: WriteRegister(apuIdx, S5B_ADDR, S5B_REG_TONE); WriteRegister(apuIdx, S5B_DATA, 0x38); // No noise, just 3 tones for now. break; } } } } }