Added EPSG audio to both suncore and MMC3
This commit is contained in:
parent
70f1a1b600
commit
5d00c055e6
19 changed files with 2192 additions and 156 deletions
|
@ -558,6 +558,7 @@
|
|||
<ClInclude Include="DummyCpu.h" />
|
||||
<ClInclude Include="Eeprom24C01.h" />
|
||||
<ClInclude Include="Eeprom24C02.h" />
|
||||
<ClInclude Include="EPSGAudio.h" />
|
||||
<ClInclude Include="EventManager.h" />
|
||||
<ClInclude Include="FaridSlrom.h" />
|
||||
<ClInclude Include="FaridUnrom.h" />
|
||||
|
@ -982,6 +983,7 @@
|
|||
<ClInclude Include="Waixing178.h" />
|
||||
<ClInclude Include="Waixing252.h" />
|
||||
<ClInclude Include="WaveRecorder.h" />
|
||||
<ClInclude Include="ym3438.h" />
|
||||
<ClInclude Include="Yoko.h" />
|
||||
<ClInclude Include="Zapper.h" />
|
||||
<ClInclude Include="PgoUtilities.h" />
|
||||
|
@ -1098,6 +1100,7 @@
|
|||
<ClCompile Include="VsControlManager.cpp" />
|
||||
<ClCompile Include="ScaleFilter.cpp" />
|
||||
<ClCompile Include="WaveRecorder.cpp" />
|
||||
<ClCompile Include="ym3438.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -116,6 +116,9 @@
|
|||
<Filter Include="Nes\MemoryManager">
|
||||
<UniqueIdentifier>{13af8497-e820-43f1-9888-85797a29b551}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Nes\Mappers\EPSG">
|
||||
<UniqueIdentifier>{c9c48ea8-7684-4959-9266-c0b4f0f86956}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="IAudioDevice.h">
|
||||
|
@ -1502,6 +1505,12 @@
|
|||
<ClInclude Include="VbController.h">
|
||||
<Filter>Nes\Input\Controllers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ym3438.h">
|
||||
<Filter>Nes\Mappers\EPSG</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EPSGAudio.h">
|
||||
<Filter>Nes\Mappers\EPSG</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -1804,5 +1813,8 @@
|
|||
<ClCompile Include="StudyBoxLoader.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ym3438.cpp">
|
||||
<Filter>Nes\Mappers\EPSG</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
163
Core/EPSGAudio.h
Normal file
163
Core/EPSGAudio.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "APU.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
#include "SSGAudio.h"
|
||||
#include "Console.h"
|
||||
|
||||
#include <array>
|
||||
#include "ym3438.h"
|
||||
|
||||
using EPSGSSGAudio = SSGAudio<AudioChannel::EPSG_L, AudioChannel::EPSG_R>;
|
||||
|
||||
class EPSGAudio : public EPSGSSGAudio
|
||||
{
|
||||
private:
|
||||
ym3438_t _chip;
|
||||
|
||||
int16_t _lastOutputs[2];
|
||||
int16_t _currentOutputs[2];
|
||||
|
||||
double _clock;
|
||||
|
||||
static constexpr uint8_t cycleCount = 24;
|
||||
|
||||
struct InputEntry
|
||||
{
|
||||
uint8_t addr = 0;
|
||||
uint8_t data = 0;
|
||||
uint8_t cycle = 0;
|
||||
uint8_t wrote = 0;
|
||||
};
|
||||
|
||||
static constexpr uint8_t INPUT_BUFFER_SIZE = cycleCount;
|
||||
using InputBuffer = std::array<InputEntry, INPUT_BUFFER_SIZE>;
|
||||
InputBuffer _inputBuffer;
|
||||
|
||||
void UpdateOutputLevel()
|
||||
{
|
||||
int16_t summedOutput = 0;
|
||||
for (size_t x = 0; x < 2; x++)
|
||||
{
|
||||
_console->GetApu()->AddExpansionAudioDelta(x == 0 ? AudioChannel::EPSG_L : AudioChannel::EPSG_R, _currentOutputs[x] - _lastOutputs[x]);
|
||||
_lastOutputs[x] = _currentOutputs[x];
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GetCurrentCycle() const
|
||||
{
|
||||
return static_cast<uint8_t>(std::floor(_clock)) % cycleCount;
|
||||
}
|
||||
|
||||
void WriteToChip(uint8_t a, uint8_t d)
|
||||
{
|
||||
const auto cycle = GetCurrentCycle();
|
||||
|
||||
if (_inputBuffer[cycle].wrote)
|
||||
{
|
||||
std::cout << "DOUBLE WRITE" << std::endl;
|
||||
}
|
||||
|
||||
_inputBuffer[cycle] = {
|
||||
a,
|
||||
d,
|
||||
cycle,
|
||||
true
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t getClockFrequency()
|
||||
{
|
||||
return _console->GetSettings()->GetEPSGClockFrequency() / 6;
|
||||
}
|
||||
|
||||
protected:
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
EPSGSSGAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<int16_t> lastOutputs{ _lastOutputs, 2 };
|
||||
ArrayInfo<int16_t> currentOutputs{ _currentOutputs, 2 };
|
||||
ArrayInfo<InputBuffer> inputBuffer{ &_inputBuffer };
|
||||
ValueInfo<ym3438_t> chip{ &_chip };
|
||||
ValueInfo<double> clock { &_clock };
|
||||
Stream(lastOutputs, currentOutputs, inputBuffer, chip, clock);
|
||||
}
|
||||
|
||||
void ClockAudio() override
|
||||
{
|
||||
EPSGSSGAudio::ClockAudio();
|
||||
|
||||
_clock += getClockFrequency() / (double)_console->GetCpu()->GetClockRate(_console->GetModel());
|
||||
|
||||
while (_clock >= cycleCount)
|
||||
{
|
||||
for (uint8_t x = 0; x < 2; x++)
|
||||
{
|
||||
_currentOutputs[x] = 0;
|
||||
}
|
||||
|
||||
for (uint8_t cycle = 0; cycle < cycleCount; cycle++)
|
||||
{
|
||||
_clock--;
|
||||
|
||||
int16_t samples[2];
|
||||
OPN2_Clock(&_chip, samples);
|
||||
|
||||
for (uint8_t x = 0; x < 2; x++)
|
||||
{
|
||||
_currentOutputs[x] += samples[x];
|
||||
}
|
||||
|
||||
auto& input = _inputBuffer[cycle];
|
||||
if(input.wrote)
|
||||
{
|
||||
input.wrote = false;
|
||||
|
||||
OPN2_Write(&_chip, input.addr, input.data);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x = 0; x < 2; x++)
|
||||
{
|
||||
_currentOutputs[x] *= 11;
|
||||
}
|
||||
|
||||
UpdateOutputLevel();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
EPSGAudio(shared_ptr<Console> console) : EPSGSSGAudio(console)
|
||||
{
|
||||
memset(_lastOutputs, 0, sizeof(_lastOutputs));
|
||||
memset(_currentOutputs, 0, sizeof(_currentOutputs));
|
||||
_inputBuffer = {};
|
||||
|
||||
_clock = 0;
|
||||
|
||||
OPN2_Reset(&_chip);
|
||||
OPN2_SetChipType(ym3438_mode_ym2612 | ym3438_mode_readmode);
|
||||
//OPN2_SetChipType(0);
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
EPSGSSGAudio::WriteRegister(addr, value);
|
||||
|
||||
switch(addr) {
|
||||
case 0xC000:
|
||||
case 0xE000:
|
||||
case 0xC002:
|
||||
case 0xE002:
|
||||
|
||||
const uint8_t a0 = (addr & 0xF000) == 0xE000;
|
||||
const uint8_t a1 = !!(addr & 0xF);
|
||||
|
||||
WriteToChip(a0 | (a1 << 1), value);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -116,7 +116,9 @@ enum class AudioChannel
|
|||
VRC6 = 7,
|
||||
VRC7 = 8,
|
||||
Namco163 = 9,
|
||||
Sunsoft5B = 10
|
||||
Sunsoft5B = 10,
|
||||
EPSG_L = 11,
|
||||
EPSG_R = 12,
|
||||
};
|
||||
|
||||
enum class EqualizerFilterType
|
||||
|
@ -657,8 +659,9 @@ private:
|
|||
|
||||
bool _audioSettingsChanged = false;
|
||||
uint32_t _audioLatency = 50;
|
||||
double _channelVolume[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
|
||||
double _channelPanning[11] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
|
||||
uint32_t _EPSGClockFrequency = 3579545;
|
||||
double _channelVolume[13] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 };
|
||||
double _channelPanning[13] = { 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 2.0 };
|
||||
EqualizerFilterType _equalizerFilterType = EqualizerFilterType::None;
|
||||
vector<double> _bandGains = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
|
||||
vector<double> _bands = { { 40,56,80,113,160,225,320,450,600,750,1000,2000,3000,4000,5000,6000,7000,10000,12500,15000 } };
|
||||
|
@ -987,6 +990,12 @@ public:
|
|||
_audioSettingsChanged = true;
|
||||
}
|
||||
|
||||
void SetEPSGClockFrequency(uint32_t clockFrequency)
|
||||
{
|
||||
_EPSGClockFrequency = clockFrequency;
|
||||
_audioSettingsChanged = true;
|
||||
}
|
||||
|
||||
void SetAudioFilterSettings(AudioFilterSettings settings)
|
||||
{
|
||||
_audioFilterSettings = settings;
|
||||
|
@ -1158,6 +1167,11 @@ public:
|
|||
return _audioLatency;
|
||||
}
|
||||
|
||||
uint32_t GetEPSGClockFrequency()
|
||||
{
|
||||
return _EPSGClockFrequency;
|
||||
}
|
||||
|
||||
void SetVideoFilterType(VideoFilterType videoFilterType)
|
||||
{
|
||||
_videoFilterType = videoFilterType;
|
||||
|
|
32
Core/MMC3.h
32
Core/MMC3.h
|
@ -5,9 +5,29 @@
|
|||
#include "CPU.h"
|
||||
#include "EmulationSettings.h"
|
||||
#include "A12Watcher.h"
|
||||
#include "EPSGAudio.h"
|
||||
#include "Sunsoft5bAudio.h"
|
||||
|
||||
#ifndef MMC3_DEFAULT_AUDIO
|
||||
#define MMC3_USE_EPSG
|
||||
#endif
|
||||
|
||||
#ifdef MMC3_USE_EPSG
|
||||
using AudioClass = EPSGAudio;
|
||||
#else
|
||||
using AudioClass = Sunsoft5bAudio;
|
||||
#endif
|
||||
|
||||
class MMC3 : public BaseMapper
|
||||
{
|
||||
public:
|
||||
unique_ptr<AudioClass> _audio;
|
||||
|
||||
void ProcessCpuClock() override
|
||||
{
|
||||
_audio->Clock();
|
||||
}
|
||||
|
||||
private:
|
||||
enum class MMC3Registers
|
||||
{
|
||||
|
@ -188,9 +208,10 @@ class MMC3 : public BaseMapper
|
|||
BaseMapper::StreamState(saving);
|
||||
ArrayInfo<uint8_t> registers = { _registers, 8 };
|
||||
SnapshotInfo a12Watcher{ &_a12Watcher };
|
||||
SnapshotInfo audio{ _audio.get() };
|
||||
Stream(_state.Reg8000, _state.RegA000, _state.RegA001, _currentRegister, _chrMode, _prgMode,
|
||||
_irqReloadValue, _irqCounter, _irqReload, _irqEnabled, a12Watcher,
|
||||
_wramEnabled, _wramWriteProtected, registers);
|
||||
_wramEnabled, _wramWriteProtected, registers, audio);
|
||||
}
|
||||
|
||||
virtual uint16_t GetPRGPageSize() override { return 0x2000; }
|
||||
|
@ -200,6 +221,8 @@ class MMC3 : public BaseMapper
|
|||
|
||||
virtual void InitMapper() override
|
||||
{
|
||||
_audio.reset(new AudioClass(_console));
|
||||
|
||||
//Force MMC3A irqs for boards that are known to use the A revision.
|
||||
//Some MMC3B boards also have the A behavior, but currently no way to tell them apart.
|
||||
_forceMmc3RevAIrqs = _romInfo.DatabaseInfo.Chip.substr(0, 5).compare("MMC3A") == 0;
|
||||
|
@ -255,6 +278,13 @@ class MMC3 : public BaseMapper
|
|||
_irqEnabled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (addr & 0xE000) {
|
||||
case 0xC000:
|
||||
case 0xE000:
|
||||
_audio->WriteRegister(addr, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TriggerIrq()
|
||||
|
|
135
Core/SSGAudio.h
Normal file
135
Core/SSGAudio.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "APU.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
#include "Console.h"
|
||||
|
||||
|
||||
template<AudioChannel...channels>
|
||||
class SSGAudio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
uint8_t _volumeLut[0x10];
|
||||
uint8_t _currentRegister;
|
||||
uint8_t _registers[0x10];
|
||||
int16_t _lastOutput;
|
||||
int16_t _timer[3];
|
||||
uint8_t _toneStep[3];
|
||||
bool _processTick;
|
||||
|
||||
uint16_t GetPeriod(int channel)
|
||||
{
|
||||
return _registers[channel * 2] | (_registers[channel * 2 + 1] << 8);
|
||||
}
|
||||
|
||||
uint16_t GetEnvelopePeriod()
|
||||
{
|
||||
return _registers[0x0B] | (_registers[0x0C] << 8);
|
||||
}
|
||||
|
||||
uint8_t GetNoisePeriod()
|
||||
{
|
||||
return _registers[6];
|
||||
}
|
||||
|
||||
uint8_t GetVolume(int channel)
|
||||
{
|
||||
return _volumeLut[_registers[8 + channel] & 0x0F];
|
||||
}
|
||||
|
||||
bool IsEnvelopeEnabled(int channel)
|
||||
{
|
||||
return (_registers[8 + channel] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
bool IsToneEnabled(int channel)
|
||||
{
|
||||
return ((_registers[7] >> channel) & 0x01) == 0x00;
|
||||
}
|
||||
|
||||
bool IsNoiseEnabled(int channel)
|
||||
{
|
||||
return ((_registers[7] >> (channel + 3)) & 0x01) == 0x00;
|
||||
}
|
||||
|
||||
void UpdateChannel(int channel)
|
||||
{
|
||||
_timer[channel]--;
|
||||
if(_timer[channel] <= 0) {
|
||||
_timer[channel] = GetPeriod(channel);
|
||||
_toneStep[channel] = (_toneStep[channel] + 1) & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOutputLevel()
|
||||
{
|
||||
int16_t summedOutput = 0;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
if(IsToneEnabled(i) && _toneStep[i] < 0x08) {
|
||||
summedOutput += GetVolume(i);
|
||||
}
|
||||
}
|
||||
|
||||
const auto delta = (summedOutput - _lastOutput) * 15;
|
||||
(_console->GetApu()->AddExpansionAudioDelta(channels, summedOutput - _lastOutput), ...);
|
||||
_lastOutput = summedOutput;
|
||||
}
|
||||
|
||||
protected:
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<int16_t> timer{ _timer, 3 };
|
||||
ArrayInfo<uint8_t> registers{ _registers, 0x10 };
|
||||
ArrayInfo<uint8_t> toneStep{ _toneStep, 3 };
|
||||
Stream(timer, registers, toneStep, _currentRegister, _lastOutput, _processTick);
|
||||
}
|
||||
|
||||
void ClockAudio() override
|
||||
{
|
||||
if(_processTick) {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
UpdateChannel(i);
|
||||
}
|
||||
UpdateOutputLevel();
|
||||
}
|
||||
_processTick = !_processTick;
|
||||
}
|
||||
|
||||
public:
|
||||
SSGAudio(shared_ptr<Console> console) : BaseExpansionAudio(console)
|
||||
{
|
||||
memset(_timer, 0, sizeof(_timer));
|
||||
memset(_registers, 0, sizeof(_registers));
|
||||
memset(_toneStep, 0, sizeof(_toneStep));
|
||||
_currentRegister = 0;
|
||||
_lastOutput = 0;
|
||||
_processTick = false;
|
||||
|
||||
double output = 1.0;
|
||||
_volumeLut[0] = 0;
|
||||
for(int i = 1; i < 0x10; i++) {
|
||||
//+1.5 dB 2x for every 1 step in volume
|
||||
output *= 1.1885022274370184377301224648922;
|
||||
output *= 1.1885022274370184377301224648922;
|
||||
|
||||
_volumeLut[i] = (uint8_t)output;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr) {
|
||||
case 0xC000:
|
||||
_currentRegister = value;
|
||||
break;
|
||||
|
||||
case 0xE000:
|
||||
if(_currentRegister <= 0xF)
|
||||
_registers[_currentRegister] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
|
@ -264,9 +264,12 @@ int16_t SoundMixer::GetOutputVolume(bool forRightChannel)
|
|||
GetChannelOutput(AudioChannel::FDS, forRightChannel) * 20 +
|
||||
GetChannelOutput(AudioChannel::MMC5, forRightChannel) * 43 +
|
||||
GetChannelOutput(AudioChannel::Namco163, forRightChannel) * 20 +
|
||||
GetChannelOutput(AudioChannel::Sunsoft5B, forRightChannel) * 15 +
|
||||
GetChannelOutput(AudioChannel::Sunsoft5B, forRightChannel) +
|
||||
GetChannelOutput(AudioChannel::VRC6, forRightChannel) * 75 +
|
||||
GetChannelOutput(AudioChannel::VRC7, forRightChannel));
|
||||
GetChannelOutput(AudioChannel::VRC7, forRightChannel) +
|
||||
GetChannelOutput(AudioChannel::EPSG_L, forRightChannel) +
|
||||
GetChannelOutput(AudioChannel::EPSG_R, forRightChannel)
|
||||
);
|
||||
}
|
||||
|
||||
void SoundMixer::AddDelta(AudioChannel channel, uint32_t time, int16_t delta)
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
private:
|
||||
static constexpr uint32_t MaxSampleRate = 96000;
|
||||
static constexpr uint32_t MaxSamplesPerFrame = MaxSampleRate / 60 * 4 * 2; //x4 to allow CPU overclocking up to 10x, x2 for panning stereo
|
||||
static constexpr uint32_t MaxChannelCount = 11;
|
||||
static constexpr uint32_t MaxChannelCount = 13;
|
||||
|
||||
IAudioDevice* _audioDevice;
|
||||
EmulationSettings* _settings;
|
||||
|
|
|
@ -2,130 +2,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "Snapshotable.h"
|
||||
#include "APU.h"
|
||||
#include "BaseExpansionAudio.h"
|
||||
#include "SSGAudio.h"
|
||||
#include "Console.h"
|
||||
|
||||
class Sunsoft5bAudio : public BaseExpansionAudio
|
||||
{
|
||||
private:
|
||||
uint8_t _volumeLut[0x10];
|
||||
uint8_t _currentRegister;
|
||||
uint8_t _registers[0x10];
|
||||
int16_t _lastOutput;
|
||||
int16_t _timer[3];
|
||||
uint8_t _toneStep[3];
|
||||
bool _processTick;
|
||||
|
||||
uint16_t GetPeriod(int channel)
|
||||
{
|
||||
return _registers[channel * 2] | (_registers[channel * 2 + 1] << 8);
|
||||
}
|
||||
|
||||
uint16_t GetEnvelopePeriod()
|
||||
{
|
||||
return _registers[0x0B] | (_registers[0x0C] << 8);
|
||||
}
|
||||
|
||||
uint8_t GetNoisePeriod()
|
||||
{
|
||||
return _registers[6];
|
||||
}
|
||||
|
||||
uint8_t GetVolume(int channel)
|
||||
{
|
||||
return _volumeLut[_registers[8 + channel] & 0x0F];
|
||||
}
|
||||
|
||||
bool IsEnvelopeEnabled(int channel)
|
||||
{
|
||||
return (_registers[8 + channel] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
bool IsToneEnabled(int channel)
|
||||
{
|
||||
return ((_registers[7] >> channel) & 0x01) == 0x00;
|
||||
}
|
||||
|
||||
bool IsNoiseEnabled(int channel)
|
||||
{
|
||||
return ((_registers[7] >> (channel + 3)) & 0x01) == 0x00;
|
||||
}
|
||||
|
||||
void UpdateChannel(int channel)
|
||||
{
|
||||
_timer[channel]--;
|
||||
if(_timer[channel] <= 0) {
|
||||
_timer[channel] = GetPeriod(channel);
|
||||
_toneStep[channel] = (_toneStep[channel] + 1) & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateOutputLevel()
|
||||
{
|
||||
int16_t summedOutput = 0;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
if(IsToneEnabled(i) && _toneStep[i] < 0x08) {
|
||||
summedOutput += GetVolume(i);
|
||||
}
|
||||
}
|
||||
|
||||
_console->GetApu()->AddExpansionAudioDelta(AudioChannel::Sunsoft5B, summedOutput - _lastOutput);
|
||||
_lastOutput = summedOutput;
|
||||
}
|
||||
|
||||
protected:
|
||||
void StreamState(bool saving) override
|
||||
{
|
||||
BaseExpansionAudio::StreamState(saving);
|
||||
|
||||
ArrayInfo<int16_t> timer{ _timer, 3 };
|
||||
ArrayInfo<uint8_t> registers{ _registers, 0x10 };
|
||||
ArrayInfo<uint8_t> toneStep{ _toneStep, 3 };
|
||||
Stream(timer, registers, toneStep, _currentRegister, _lastOutput, _processTick);
|
||||
}
|
||||
|
||||
void ClockAudio() override
|
||||
{
|
||||
if(_processTick) {
|
||||
for(int i = 0; i < 3; i++) {
|
||||
UpdateChannel(i);
|
||||
}
|
||||
UpdateOutputLevel();
|
||||
}
|
||||
_processTick = !_processTick;
|
||||
}
|
||||
|
||||
public:
|
||||
Sunsoft5bAudio(shared_ptr<Console> console) : BaseExpansionAudio(console)
|
||||
{
|
||||
memset(_timer, 0, sizeof(_timer));
|
||||
memset(_registers, 0, sizeof(_registers));
|
||||
memset(_toneStep, 0, sizeof(_toneStep));
|
||||
_currentRegister = 0;
|
||||
_lastOutput = 0;
|
||||
_processTick = false;
|
||||
|
||||
double output = 1.0;
|
||||
_volumeLut[0] = 0;
|
||||
for(int i = 1; i < 0x10; i++) {
|
||||
//+1.5 dB 2x for every 1 step in volume
|
||||
output *= 1.1885022274370184377301224648922;
|
||||
output *= 1.1885022274370184377301224648922;
|
||||
|
||||
_volumeLut[i] = (uint8_t)output;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteRegister(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr & 0xE000) {
|
||||
case 0xC000:
|
||||
_currentRegister = value & 0x0F;
|
||||
break;
|
||||
|
||||
case 0xE000:
|
||||
_registers[_currentRegister] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
using Sunsoft5bAudio = SSGAudio<AudioChannel::Sunsoft5B>;
|
|
@ -3,11 +3,22 @@
|
|||
#include "BaseMapper.h"
|
||||
#include "CPU.h"
|
||||
#include "Sunsoft5bAudio.h"
|
||||
#include "EPSGAudio.h"
|
||||
|
||||
#ifndef SUNSOFT_DEFAULT_AUDIO
|
||||
#define SUNSOFT_USE_EPSG
|
||||
#endif
|
||||
|
||||
#ifdef SUNSOFT_USE_EPSG
|
||||
using AudioClass = EPSGAudio;
|
||||
#else
|
||||
using AudioClass = Sunsoft5bAudio;
|
||||
#endif
|
||||
|
||||
class SunsoftFme7 : public BaseMapper
|
||||
{
|
||||
private:
|
||||
unique_ptr<Sunsoft5bAudio> _audio;
|
||||
unique_ptr<AudioClass> _audio;
|
||||
uint8_t _command;
|
||||
uint8_t _workRamValue;
|
||||
bool _irqEnabled;
|
||||
|
@ -24,7 +35,7 @@ protected:
|
|||
|
||||
void InitMapper() override
|
||||
{
|
||||
_audio.reset(new Sunsoft5bAudio(_console));
|
||||
_audio.reset(new AudioClass(_console));
|
||||
|
||||
_command = 0;
|
||||
_workRamValue = 0;
|
||||
|
|
1429
Core/ym3438.cpp
Normal file
1429
Core/ym3438.cpp
Normal file
File diff suppressed because it is too large
Load diff
211
Core/ym3438.h
Normal file
211
Core/ym3438.h
Normal file
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2017-2018 Alexey Khokholov (Nuke.YKT)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Nuked OPN2(Yamaha YM3438) emulator.
|
||||
* Thanks:
|
||||
* Silicon Pr0n:
|
||||
* Yamaha YM3438 decap and die shot(digshadow).
|
||||
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
||||
* OPL2 ROMs.
|
||||
*
|
||||
* version: 1.0.9
|
||||
*/
|
||||
|
||||
#ifndef YM3438_H
|
||||
#define YM3438_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
ym3438_mode_ym2612 = 0x01, /* Enables YM2612 emulation (MD1, MD2 VA2) */
|
||||
ym3438_mode_readmode = 0x02 /* Enables status read on any port (TeraDrive, MD1 VA7, MD2, etc) */
|
||||
};
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uintptr_t Bitu;
|
||||
typedef intptr_t Bits;
|
||||
typedef uint64_t Bit64u;
|
||||
typedef int64_t Bit64s;
|
||||
typedef uint32_t Bit32u;
|
||||
typedef int32_t Bit32s;
|
||||
typedef uint16_t Bit16u;
|
||||
typedef int16_t Bit16s;
|
||||
typedef uint8_t Bit8u;
|
||||
typedef int8_t Bit8s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Bit32u cycles;
|
||||
Bit32u channel;
|
||||
Bit16s mol, mor;
|
||||
/* IO */
|
||||
Bit16u write_data;
|
||||
Bit8u write_a;
|
||||
Bit8u write_d;
|
||||
Bit8u write_a_en;
|
||||
Bit8u write_d_en;
|
||||
Bit8u write_busy;
|
||||
Bit8u write_busy_cnt;
|
||||
Bit8u write_fm_address;
|
||||
Bit8u write_fm_data;
|
||||
Bit16u write_fm_mode_a;
|
||||
Bit16u address;
|
||||
Bit8u data;
|
||||
Bit8u pin_test_in;
|
||||
Bit8u pin_irq;
|
||||
Bit8u busy;
|
||||
/* LFO */
|
||||
Bit8u lfo_en;
|
||||
Bit8u lfo_freq;
|
||||
Bit8u lfo_pm;
|
||||
Bit8u lfo_am;
|
||||
Bit8u lfo_cnt;
|
||||
Bit8u lfo_inc;
|
||||
Bit8u lfo_quotient;
|
||||
/* Phase generator */
|
||||
Bit16u pg_fnum;
|
||||
Bit8u pg_block;
|
||||
Bit8u pg_kcode;
|
||||
Bit32u pg_inc[24];
|
||||
Bit32u pg_phase[24];
|
||||
Bit8u pg_reset[24];
|
||||
Bit32u pg_read;
|
||||
/* Envelope generator */
|
||||
Bit8u eg_cycle;
|
||||
Bit8u eg_cycle_stop;
|
||||
Bit8u eg_shift;
|
||||
Bit8u eg_shift_lock;
|
||||
Bit8u eg_timer_low_lock;
|
||||
Bit16u eg_timer;
|
||||
Bit8u eg_timer_inc;
|
||||
Bit16u eg_quotient;
|
||||
Bit8u eg_custom_timer;
|
||||
Bit8u eg_rate;
|
||||
Bit8u eg_ksv;
|
||||
Bit8u eg_inc;
|
||||
Bit8u eg_ratemax;
|
||||
Bit8u eg_sl[2];
|
||||
Bit8u eg_lfo_am;
|
||||
Bit8u eg_tl[2];
|
||||
Bit8u eg_state[24];
|
||||
Bit16u eg_level[24];
|
||||
Bit16u eg_out[24];
|
||||
Bit8u eg_kon[24];
|
||||
Bit8u eg_kon_csm[24];
|
||||
Bit8u eg_kon_latch[24];
|
||||
Bit8u eg_csm_mode[24];
|
||||
Bit8u eg_ssg_enable[24];
|
||||
Bit8u eg_ssg_pgrst_latch[24];
|
||||
Bit8u eg_ssg_repeat_latch[24];
|
||||
Bit8u eg_ssg_hold_up_latch[24];
|
||||
Bit8u eg_ssg_dir[24];
|
||||
Bit8u eg_ssg_inv[24];
|
||||
Bit32u eg_read[2];
|
||||
Bit8u eg_read_inc;
|
||||
/* FM */
|
||||
Bit16s fm_op1[6][2];
|
||||
Bit16s fm_op2[6];
|
||||
Bit16s fm_out[24];
|
||||
Bit16u fm_mod[24];
|
||||
/* Channel */
|
||||
Bit16s ch_acc[6];
|
||||
Bit16s ch_out[6];
|
||||
Bit16s ch_lock;
|
||||
Bit8u ch_lock_l;
|
||||
Bit8u ch_lock_r;
|
||||
Bit16s ch_read;
|
||||
/* Timer */
|
||||
Bit16u timer_a_cnt;
|
||||
Bit16u timer_a_reg;
|
||||
Bit8u timer_a_load_lock;
|
||||
Bit8u timer_a_load;
|
||||
Bit8u timer_a_enable;
|
||||
Bit8u timer_a_reset;
|
||||
Bit8u timer_a_load_latch;
|
||||
Bit8u timer_a_overflow_flag;
|
||||
Bit8u timer_a_overflow;
|
||||
|
||||
Bit16u timer_b_cnt;
|
||||
Bit8u timer_b_subcnt;
|
||||
Bit16u timer_b_reg;
|
||||
Bit8u timer_b_load_lock;
|
||||
Bit8u timer_b_load;
|
||||
Bit8u timer_b_enable;
|
||||
Bit8u timer_b_reset;
|
||||
Bit8u timer_b_load_latch;
|
||||
Bit8u timer_b_overflow_flag;
|
||||
Bit8u timer_b_overflow;
|
||||
|
||||
/* Register set */
|
||||
Bit8u mode_test_21[8];
|
||||
Bit8u mode_test_2c[8];
|
||||
Bit8u mode_ch3;
|
||||
Bit8u mode_kon_channel;
|
||||
Bit8u mode_kon_operator[4];
|
||||
Bit8u mode_kon[24];
|
||||
Bit8u mode_csm;
|
||||
Bit8u mode_kon_csm;
|
||||
Bit8u dacen;
|
||||
Bit16s dacdata;
|
||||
|
||||
Bit8u ks[24];
|
||||
Bit8u ar[24];
|
||||
Bit8u sr[24];
|
||||
Bit8u dt[24];
|
||||
Bit8u multi[24];
|
||||
Bit8u sl[24];
|
||||
Bit8u rr[24];
|
||||
Bit8u dr[24];
|
||||
Bit8u am[24];
|
||||
Bit8u tl[24];
|
||||
Bit8u ssg_eg[24];
|
||||
|
||||
Bit16u fnum[6];
|
||||
Bit8u block[6];
|
||||
Bit8u kcode[6];
|
||||
Bit16u fnum_3ch[6];
|
||||
Bit8u block_3ch[6];
|
||||
Bit8u kcode_3ch[6];
|
||||
Bit8u reg_a4;
|
||||
Bit8u reg_ac;
|
||||
Bit8u connect[6];
|
||||
Bit8u fb[6];
|
||||
Bit8u pan_l[6], pan_r[6];
|
||||
Bit8u ams[6];
|
||||
Bit8u pms[6];
|
||||
Bit8u status;
|
||||
Bit32u status_time;
|
||||
} ym3438_t;
|
||||
|
||||
void OPN2_Reset(ym3438_t *chip);
|
||||
void OPN2_SetChipType(Bit32u type);
|
||||
void OPN2_Clock(ym3438_t *chip, Bit16s *buffer);
|
||||
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data);
|
||||
void OPN2_SetTestPin(ym3438_t *chip, Bit32u value);
|
||||
Bit32u OPN2_ReadTestPin(ym3438_t *chip);
|
||||
Bit32u OPN2_ReadIRQPin(ym3438_t *chip);
|
||||
Bit8u OPN2_Read(ym3438_t *chip, Bit32u port);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -23,6 +23,10 @@ namespace Mesen.GUI.Config
|
|||
[MinMax(0, 100)] public UInt32 Vrc7Volume = 100;
|
||||
[MinMax(0, 100)] public UInt32 Namco163Volume = 100;
|
||||
[MinMax(0, 100)] public UInt32 Sunsoft5bVolume = 100;
|
||||
[MinMax(0, 100)] public UInt32 EPSGVolume_L = 100;
|
||||
[MinMax(0, 100)] public UInt32 EPSGVolume_R = 100;
|
||||
|
||||
[MinMax(10000, 32000000)] public UInt32 EPSGClockFrequency = 3579545;
|
||||
|
||||
[MinMax(-100, 100)] public Int32 Square1Panning = 0;
|
||||
[MinMax(-100, 100)] public Int32 Square2Panning = 0;
|
||||
|
@ -35,6 +39,8 @@ namespace Mesen.GUI.Config
|
|||
[MinMax(-100, 100)] public Int32 Vrc7Panning = 0;
|
||||
[MinMax(-100, 100)] public Int32 Namco163Panning = 0;
|
||||
[MinMax(-100, 100)] public Int32 Sunsoft5bPanning = 0;
|
||||
[MinMax(-100, 100)] public Int32 EPSGPanning_L = -100;
|
||||
[MinMax(-100, 100)] public Int32 EPSGPanning_R = 100;
|
||||
|
||||
[ValidValues(11025, 22050, 44100, 48000, 96000)] public UInt32 SampleRate = 48000;
|
||||
public bool ReduceSoundInBackground = true;
|
||||
|
@ -87,7 +93,7 @@ namespace Mesen.GUI.Config
|
|||
{
|
||||
}
|
||||
|
||||
static private double ConvertVolume(UInt32 volume)
|
||||
static public double ConvertVolume(UInt32 volume)
|
||||
{
|
||||
return ((double)volume / 100d);
|
||||
}
|
||||
|
@ -114,6 +120,8 @@ namespace Mesen.GUI.Config
|
|||
InteropEmu.SetChannelVolume(AudioChannel.VRC7, ConvertVolume(audioInfo.Vrc7Volume));
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Namco163, ConvertVolume(audioInfo.Namco163Volume));
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Sunsoft5B, ConvertVolume(audioInfo.Sunsoft5bVolume));
|
||||
InteropEmu.SetChannelVolume(AudioChannel.EPSG_L, ConvertVolume(audioInfo.EPSGVolume_L));
|
||||
InteropEmu.SetChannelVolume(AudioChannel.EPSG_R, ConvertVolume(audioInfo.EPSGVolume_R));
|
||||
|
||||
InteropEmu.SetChannelPanning(AudioChannel.Square1, ConvertPanning(audioInfo.Square1Panning));
|
||||
InteropEmu.SetChannelPanning(AudioChannel.Square2, ConvertPanning(audioInfo.Square2Panning));
|
||||
|
@ -126,6 +134,10 @@ namespace Mesen.GUI.Config
|
|||
InteropEmu.SetChannelPanning(AudioChannel.VRC7, ConvertPanning(audioInfo.Vrc7Panning));
|
||||
InteropEmu.SetChannelPanning(AudioChannel.Namco163, ConvertPanning(audioInfo.Namco163Panning));
|
||||
InteropEmu.SetChannelPanning(AudioChannel.Sunsoft5B, ConvertPanning(audioInfo.Sunsoft5bPanning));
|
||||
InteropEmu.SetChannelPanning(AudioChannel.EPSG_L, ConvertPanning(audioInfo.EPSGPanning_L));
|
||||
InteropEmu.SetChannelPanning(AudioChannel.EPSG_R, ConvertPanning(audioInfo.EPSGPanning_R));
|
||||
|
||||
InteropEmu.SetEPSGClockFrequency(audioInfo.EPSGClockFrequency);
|
||||
|
||||
InteropEmu.SetEqualizerFilterType(audioInfo.EnableEqualizer ? audioInfo.EqualizerFilterType : EqualizerFilterType.None);
|
||||
|
||||
|
|
17
GUI.NET/Debugger/frmApuViewer.Designer.cs
generated
17
GUI.NET/Debugger/frmApuViewer.Designer.cs
generated
|
@ -41,6 +41,7 @@
|
|||
this.chkVrc7 = new System.Windows.Forms.CheckBox();
|
||||
this.chkDmc = new System.Windows.Forms.CheckBox();
|
||||
this.chkSunsoft = new System.Windows.Forms.CheckBox();
|
||||
this.chkEPSG = new System.Windows.Forms.CheckBox();
|
||||
this.chkVrc6 = new System.Windows.Forms.CheckBox();
|
||||
this.grpSquare1 = new System.Windows.Forms.GroupBox();
|
||||
this.ctrlSquareInfo1 = new Mesen.GUI.Debugger.Controls.ctrlSquareInfo();
|
||||
|
@ -118,6 +119,7 @@
|
|||
this.tableLayoutPanel2.Controls.Add(this.chkVrc7, 2, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkDmc, 0, 4);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkSunsoft, 1, 3);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkEPSG, 1, 4);
|
||||
this.tableLayoutPanel2.Controls.Add(this.chkVrc6, 2, 0);
|
||||
this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
|
||||
|
@ -271,6 +273,20 @@
|
|||
this.chkSunsoft.UseVisualStyleBackColor = true;
|
||||
this.chkSunsoft.CheckedChanged += new System.EventHandler(this.chkSoundChannel_CheckedChanged);
|
||||
//
|
||||
// chkEPSG
|
||||
//
|
||||
this.chkEPSG.AutoSize = true;
|
||||
this.chkEPSG.Checked = true;
|
||||
this.chkEPSG.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.chkEPSG.Location = new System.Drawing.Point(99, 80);
|
||||
this.chkEPSG.Margin = new System.Windows.Forms.Padding(3, 0, 3, 3);
|
||||
this.chkEPSG.Name = "chkEPSG";
|
||||
this.chkEPSG.Size = new System.Drawing.Size(78, 17);
|
||||
this.chkEPSG.TabIndex = 10;
|
||||
this.chkEPSG.Text = "EPSG";
|
||||
this.chkEPSG.UseVisualStyleBackColor = true;
|
||||
this.chkEPSG.CheckedChanged += new System.EventHandler(this.chkSoundChannel_CheckedChanged);
|
||||
//
|
||||
// chkVrc6
|
||||
//
|
||||
this.chkVrc6.AutoSize = true;
|
||||
|
@ -459,5 +475,6 @@
|
|||
private System.Windows.Forms.CheckBox chkVrc7;
|
||||
private System.Windows.Forms.CheckBox chkVrc6;
|
||||
private System.Windows.Forms.CheckBox chkSunsoft;
|
||||
private System.Windows.Forms.CheckBox chkEPSG;
|
||||
}
|
||||
}
|
|
@ -54,7 +54,9 @@ namespace Mesen.GUI.Debugger
|
|||
}
|
||||
|
||||
private void chkSoundChannel_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
{
|
||||
AudioInfo audioInfo = ConfigManager.Config.AudioInfo;
|
||||
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Square1, chkSquare1.Checked ? 1 : 0);
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Square2, chkSquare2.Checked ? 1 : 0);
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Triangle, chkTriangle.Checked ? 1 : 0);
|
||||
|
@ -66,6 +68,8 @@ namespace Mesen.GUI.Debugger
|
|||
InteropEmu.SetChannelVolume(AudioChannel.VRC7, chkVrc7.Checked ? 1 : 0);
|
||||
InteropEmu.SetChannelVolume(AudioChannel.MMC5, chkMmc5.Checked ? 1 : 0);
|
||||
InteropEmu.SetChannelVolume(AudioChannel.Sunsoft5B, chkSunsoft.Checked ? 1 : 0);
|
||||
}
|
||||
InteropEmu.SetChannelVolume(AudioChannel.EPSG_L, chkEPSG.Checked ? AudioInfo.ConvertVolume(audioInfo.EPSGVolume_L) : 0);
|
||||
InteropEmu.SetChannelVolume(AudioChannel.EPSG_R, chkEPSG.Checked ? AudioInfo.ConvertVolume(audioInfo.EPSGVolume_R) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
139
GUI.NET/Forms/Config/frmAudioConfig.Designer.cs
generated
139
GUI.NET/Forms/Config/frmAudioConfig.Designer.cs
generated
|
@ -43,6 +43,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.trkVrc7Vol = new Mesen.GUI.Controls.ctrlTrackbar();
|
||||
this.trkNamco163Vol = new Mesen.GUI.Controls.ctrlTrackbar();
|
||||
this.trkSunsoft5b = new Mesen.GUI.Controls.ctrlTrackbar();
|
||||
this.trkEPSGVol_L = new Mesen.GUI.Controls.ctrlTrackbar();
|
||||
this.trkEPSGVol_R = new Mesen.GUI.Controls.ctrlTrackbar();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.lblVolumeReductionSettings = new System.Windows.Forms.Label();
|
||||
this.chkEnableAudio = new System.Windows.Forms.CheckBox();
|
||||
|
@ -78,6 +80,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.trkVrc7Pan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkNamcoPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkSunsoftPan = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkEPSGPan_L = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkEPSGPan_R = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.tpgEqualizer = new System.Windows.Forms.TabPage();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.chkEnableEqualizer = new System.Windows.Forms.CheckBox();
|
||||
|
@ -142,6 +146,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkDisableDynamicSampleRate = new Mesen.GUI.Controls.ctrlRiskyOption();
|
||||
this.chkDisableNoiseModeFlag = new Mesen.GUI.Controls.ctrlRiskyOption();
|
||||
this.nudEPSGClockFrequency = new Mesen.GUI.Controls.MesenNumericUpDown();
|
||||
this.lblEPSGClockFrequency = new System.Windows.Forms.Label();
|
||||
this.chkSilenceTriangleHighFreq = new System.Windows.Forms.CheckBox();
|
||||
this.chkSwapDutyCycles = new Mesen.GUI.Controls.ctrlRiskyOption();
|
||||
this.chkReduceDmcPopping = new System.Windows.Forms.CheckBox();
|
||||
|
@ -196,7 +202,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.ColumnCount = 6;
|
||||
this.tableLayoutPanel1.ColumnCount = 7;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
|
||||
|
@ -214,8 +220,10 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tableLayoutPanel1.Controls.Add(this.trkVrc6Vol, 2, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkVrc7Vol, 3, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkNamco163Vol, 4, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkSunsoft5b, 5, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkSunsoft5b, 6, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkEPSGVol_L, 5, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.trkEPSGVol_R, 6, 1);
|
||||
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 16);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
|
@ -404,10 +412,40 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.trkSunsoft5b.TabIndex = 22;
|
||||
this.trkSunsoft5b.Text = "Sunsoft";
|
||||
this.trkSunsoft5b.Value = 50;
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 2;
|
||||
//
|
||||
// trkEPSGVol_L
|
||||
//
|
||||
this.trkEPSGVol_L.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.trkEPSGVol_L.Location = new System.Drawing.Point(387, 160);
|
||||
this.trkEPSGVol_L.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkEPSGVol_L.Maximum = 100;
|
||||
this.trkEPSGVol_L.MaximumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_L.Minimum = 0;
|
||||
this.trkEPSGVol_L.MinimumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_L.Name = "trkEPSGVol_L";
|
||||
this.trkEPSGVol_L.Size = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_L.TabIndex = 22;
|
||||
this.trkEPSGVol_L.Text = "EPSG Left";
|
||||
this.trkEPSGVol_L.Value = 100;
|
||||
//
|
||||
// trkEPSGVol_R
|
||||
//
|
||||
this.trkEPSGVol_R.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.trkEPSGVol_R.Location = new System.Drawing.Point(387, 160);
|
||||
this.trkEPSGVol_R.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkEPSGVol_R.Maximum = 100;
|
||||
this.trkEPSGVol_R.MaximumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_R.Minimum = 0;
|
||||
this.trkEPSGVol_R.MinimumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_R.Name = "trkEPSGVol_R";
|
||||
this.trkEPSGVol_R.Size = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGVol_R.TabIndex = 22;
|
||||
this.trkEPSGVol_R.Text = "EPSG Right";
|
||||
this.trkEPSGVol_R.Value = 100;
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.ColumnCount = 2;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel2.Controls.Add(this.lblVolumeReductionSettings, 0, 4);
|
||||
|
@ -696,7 +734,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tabMain.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabMain.Name = "tabMain";
|
||||
this.tabMain.SelectedIndex = 0;
|
||||
this.tabMain.Size = new System.Drawing.Size(477, 373);
|
||||
this.tabMain.Size = new System.Drawing.Size(477, 389);
|
||||
this.tabMain.TabIndex = 4;
|
||||
//
|
||||
// tpgGeneral
|
||||
|
@ -727,7 +765,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tpgPanning.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgPanning.Name = "tpgPanning";
|
||||
this.tpgPanning.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgPanning.Size = new System.Drawing.Size(469, 347);
|
||||
this.tpgPanning.Size = new System.Drawing.Size(469, 389);
|
||||
this.tpgPanning.TabIndex = 4;
|
||||
this.tpgPanning.Text = "Panning";
|
||||
this.tpgPanning.UseVisualStyleBackColor = true;
|
||||
|
@ -747,11 +785,13 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tableLayoutPanel6.Controls.Add(this.trkVrc6Pan, 1, 2);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkVrc7Pan, 1, 3);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkNamcoPan, 1, 4);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkSunsoftPan, 1, 5);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkSunsoftPan, 0, 6);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkEPSGPan_L, 0, 5);
|
||||
this.tableLayoutPanel6.Controls.Add(this.trkEPSGPan_R, 1, 5);
|
||||
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel6.Location = new System.Drawing.Point(3, 3);
|
||||
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||
this.tableLayoutPanel6.RowCount = 7;
|
||||
this.tableLayoutPanel6.RowCount = 8;
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
|
@ -760,7 +800,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(463, 341);
|
||||
this.tableLayoutPanel6.Size = new System.Drawing.Size(463, 389);
|
||||
this.tableLayoutPanel6.TabIndex = 3;
|
||||
//
|
||||
// trkSquare1Pan
|
||||
|
@ -928,6 +968,36 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.trkSunsoftPan.Text = "Sunsoft";
|
||||
this.trkSunsoftPan.Value = 0;
|
||||
//
|
||||
// trkEPSGPan_L
|
||||
//
|
||||
this.trkEPSGPan_L.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.trkEPSGPan_L.Location = new System.Drawing.Point(244, 275);
|
||||
this.trkEPSGPan_L.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkEPSGPan_L.Maximum = 100;
|
||||
this.trkEPSGPan_L.MaximumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGPan_L.Minimum = -100;
|
||||
this.trkEPSGPan_L.MinimumSize = new System.Drawing.Size(206, 55);
|
||||
this.trkEPSGPan_L.Name = "trkEPSGPan_L";
|
||||
this.trkEPSGPan_L.Size = new System.Drawing.Size(206, 55);
|
||||
this.trkEPSGPan_L.TabIndex = 22;
|
||||
this.trkEPSGPan_L.Text = "EPSG Left";
|
||||
this.trkEPSGPan_L.Value = -100;
|
||||
//
|
||||
// trkEPSGPan_R
|
||||
//
|
||||
this.trkEPSGPan_R.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.trkEPSGPan_R.Location = new System.Drawing.Point(244, 275);
|
||||
this.trkEPSGPan_R.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkEPSGPan_R.Maximum = 100;
|
||||
this.trkEPSGPan_R.MaximumSize = new System.Drawing.Size(63, 160);
|
||||
this.trkEPSGPan_R.Minimum = -100;
|
||||
this.trkEPSGPan_R.MinimumSize = new System.Drawing.Size(206, 55);
|
||||
this.trkEPSGPan_R.Name = "trkEPSGPan_R";
|
||||
this.trkEPSGPan_R.Size = new System.Drawing.Size(206, 55);
|
||||
this.trkEPSGPan_R.TabIndex = 22;
|
||||
this.trkEPSGPan_R.Text = "EPSG Right";
|
||||
this.trkEPSGPan_R.Value = 100;
|
||||
//
|
||||
// tpgEqualizer
|
||||
//
|
||||
this.tpgEqualizer.Controls.Add(this.groupBox1);
|
||||
|
@ -1897,13 +1967,16 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkDisableDynamicSampleRate, 0, 2);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkDisableNoiseModeFlag, 0, 4);
|
||||
this.tableLayoutPanel3.Controls.Add(this.nudEPSGClockFrequency, 0, 5);
|
||||
this.tableLayoutPanel3.Controls.Add(this.lblEPSGClockFrequency, 0, 5);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkSilenceTriangleHighFreq, 0, 0);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkSwapDutyCycles, 0, 3);
|
||||
this.tableLayoutPanel3.Controls.Add(this.chkReduceDmcPopping, 0, 1);
|
||||
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 3);
|
||||
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||
this.tableLayoutPanel3.RowCount = 6;
|
||||
this.tableLayoutPanel3.RowCount = 7;
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 24F));
|
||||
|
@ -1932,10 +2005,36 @@ namespace Mesen.GUI.Forms.Config
|
|||
this.chkDisableNoiseModeFlag.Size = new System.Drawing.Size(463, 24);
|
||||
this.chkDisableNoiseModeFlag.TabIndex = 3;
|
||||
this.chkDisableNoiseModeFlag.Text = "Disable noise channel mode flag";
|
||||
//
|
||||
// nudEPSGClockFrequency
|
||||
//
|
||||
this.nudEPSGClockFrequency.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.nudEPSGClockFrequency.Location = new System.Drawing.Point(0, 96);
|
||||
this.nudEPSGClockFrequency.Size = new System.Drawing.Size(463, 24);
|
||||
this.nudEPSGClockFrequency.TabIndex = 3;
|
||||
this.nudEPSGClockFrequency.Text = "EPSG Clock Frquency";
|
||||
this.nudEPSGClockFrequency.Name = "nudEPSGClockFrequency";
|
||||
this.nudEPSGClockFrequency.Increment = new decimal(100000);
|
||||
this.nudEPSGClockFrequency.Minimum = new decimal(10000);
|
||||
this.nudEPSGClockFrequency.Maximum = new decimal(32000000);
|
||||
this.nudEPSGClockFrequency.Value = new decimal(0);
|
||||
this.nudEPSGClockFrequency.MaximumSize = new System.Drawing.Size(10000, 20);
|
||||
this.nudEPSGClockFrequency.MinimumSize = new System.Drawing.Size(200, 21);
|
||||
this.nudEPSGClockFrequency.DecimalPlaces = 0;
|
||||
//
|
||||
// chkSilenceTriangleHighFreq
|
||||
// lblEPSGClockFrequency
|
||||
//
|
||||
this.chkSilenceTriangleHighFreq.AutoSize = true;
|
||||
this.lblEPSGClockFrequency.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblEPSGClockFrequency.AutoSize = true;
|
||||
this.lblEPSGClockFrequency.Location = new System.Drawing.Point(163, 6);
|
||||
this.lblEPSGClockFrequency.Name = "lblEPSGClockFrequency";
|
||||
this.lblEPSGClockFrequency.Size = new System.Drawing.Size(15, 13);
|
||||
this.lblEPSGClockFrequency.TabIndex = 3;
|
||||
this.lblEPSGClockFrequency.Text = "EPSG Clock Frequency (default is 3579545Hz)";
|
||||
//
|
||||
// chkSilenceTriangleHighFreq
|
||||
//
|
||||
this.chkSilenceTriangleHighFreq.AutoSize = true;
|
||||
this.chkSilenceTriangleHighFreq.Location = new System.Drawing.Point(3, 3);
|
||||
this.chkSilenceTriangleHighFreq.Name = "chkSilenceTriangleHighFreq";
|
||||
this.chkSilenceTriangleHighFreq.Size = new System.Drawing.Size(337, 17);
|
||||
|
@ -1968,7 +2067,7 @@ namespace Mesen.GUI.Forms.Config
|
|||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(477, 402);
|
||||
this.ClientSize = new System.Drawing.Size(477, 450);
|
||||
this.Controls.Add(this.tabMain);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.MaximizeBox = false;
|
||||
|
@ -2051,7 +2150,9 @@ namespace Mesen.GUI.Forms.Config
|
|||
private Controls.ctrlTrackbar trkVrc7Vol;
|
||||
private Controls.ctrlTrackbar trkNamco163Vol;
|
||||
private Controls.ctrlTrackbar trkSunsoft5b;
|
||||
private System.Windows.Forms.TabControl tabMain;
|
||||
private Controls.ctrlTrackbar trkEPSGVol_L;
|
||||
private Controls.ctrlTrackbar trkEPSGVol_R;
|
||||
private System.Windows.Forms.TabControl tabMain;
|
||||
private System.Windows.Forms.TabPage tpgGeneral;
|
||||
private System.Windows.Forms.TabPage tpgVolume;
|
||||
private System.Windows.Forms.CheckBox chkReduceSoundInBackground;
|
||||
|
@ -2091,6 +2192,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
private Controls.ctrlHorizontalTrackbar trkVrc7Pan;
|
||||
private Controls.ctrlHorizontalTrackbar trkNamcoPan;
|
||||
private Controls.ctrlHorizontalTrackbar trkSunsoftPan;
|
||||
private Controls.ctrlHorizontalTrackbar trkEPSGPan_L;
|
||||
private Controls.ctrlHorizontalTrackbar trkEPSGPan_R;
|
||||
private Controls.ctrlHorizontalTrackbar trkSquare1Pan;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel5;
|
||||
private System.Windows.Forms.CheckBox chkCrossFeedEnabled;
|
||||
|
@ -2098,6 +2201,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
private System.Windows.Forms.Label lblCrossFeedRatio;
|
||||
private Controls.ctrlHorizontalTrackbar trkTrianglePan;
|
||||
private ctrlRiskyOption chkDisableNoiseModeFlag;
|
||||
private MesenNumericUpDown nudEPSGClockFrequency;
|
||||
private System.Windows.Forms.Label lblEPSGClockFrequency;
|
||||
private System.Windows.Forms.TabPage tpgEqualizer;
|
||||
private System.Windows.Forms.TableLayoutPanel tlpEqualizer;
|
||||
private ctrlTrackbar trkBand6Gain;
|
||||
|
|
|
@ -43,6 +43,8 @@ namespace Mesen.GUI.Forms.Config
|
|||
AddBinding("Vrc7Volume", trkVrc7Vol);
|
||||
AddBinding("Namco163Volume", trkNamco163Vol);
|
||||
AddBinding("Sunsoft5bVolume", trkSunsoft5b);
|
||||
AddBinding("EPSGVolume_L", trkEPSGVol_L);
|
||||
AddBinding("EPSGVolume_R", trkEPSGVol_R);
|
||||
|
||||
AddBinding("Square1Panning", trkSquare1Pan);
|
||||
AddBinding("Square2Panning", trkSquare2Pan);
|
||||
|
@ -55,6 +57,10 @@ namespace Mesen.GUI.Forms.Config
|
|||
AddBinding("Vrc7Panning", trkVrc7Pan);
|
||||
AddBinding("Namco163Panning", trkNamcoPan);
|
||||
AddBinding("Sunsoft5bPanning", trkSunsoftPan);
|
||||
AddBinding("EPSGPanning_L", trkEPSGPan_L);
|
||||
AddBinding("EPSGPanning_R", trkEPSGPan_R);
|
||||
|
||||
AddBinding("EPSGClockFrequency", nudEPSGClockFrequency);
|
||||
|
||||
AddBinding("AudioLatency", nudLatency);
|
||||
AddBinding("SampleRate", cboSampleRate);
|
||||
|
|
|
@ -208,6 +208,7 @@ namespace Mesen.GUI
|
|||
[DllImport(DLLPath)] public static extern void SetBandGain(int band, double gain);
|
||||
[DllImport(DLLPath)] public static extern void SetSampleRate(UInt32 sampleRate);
|
||||
[DllImport(DLLPath)] public static extern void SetAudioLatency(UInt32 msLatency);
|
||||
[DllImport(DLLPath)] public static extern void SetEPSGClockFrequency(UInt32 clockFrequency);
|
||||
[DllImport(DLLPath)] public static extern void SetAudioFilterSettings(AudioFilterSettings settings);
|
||||
[DllImport(DLLPath)] public static extern void SetRunAheadFrames(UInt32 frameCount);
|
||||
|
||||
|
@ -2297,8 +2298,10 @@ namespace Mesen.GUI
|
|||
VRC6 = 7,
|
||||
VRC7 = 8,
|
||||
Namco163 = 9,
|
||||
Sunsoft5B = 10
|
||||
}
|
||||
Sunsoft5B = 10,
|
||||
EPSG_L = 11,
|
||||
EPSG_R= 12
|
||||
}
|
||||
|
||||
public enum EqualizerFilterType
|
||||
{
|
||||
|
|
|
@ -633,6 +633,7 @@ namespace InteropEmu {
|
|||
DllExport void __stdcall SetMasterVolume(double volume, double volumeReduction, ConsoleId consoleId) { GetConsoleById(consoleId)->GetSettings()->SetMasterVolume(volume, volumeReduction); }
|
||||
DllExport void __stdcall SetSampleRate(uint32_t sampleRate) { _settings->SetSampleRate(sampleRate); }
|
||||
DllExport void __stdcall SetAudioLatency(uint32_t msLatency) { _settings->SetAudioLatency(msLatency); }
|
||||
DllExport void __stdcall SetEPSGClockFrequency(uint32_t clockFrequency) { _settings->SetEPSGClockFrequency(clockFrequency); }
|
||||
DllExport void __stdcall SetAudioFilterSettings(AudioFilterSettings settings) { _settings->SetAudioFilterSettings(settings); }
|
||||
DllExport void __stdcall SetRunAheadFrames(uint32_t frameCount) { _settings->SetRunAheadFrames(frameCount); }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue