diff --git a/Makefile b/Makefile index 5a4406a7..771e98ff 100755 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ include nall/Makefile snes := snes -profile := research +profile := accuracy ui := qt # compiler @@ -61,14 +61,14 @@ endif install: ifeq ($(platform),x) - install -D -m 755 out/bsnes $(DESTDIR)$(prefix)/bin/bsnes + install -D -m 755 out/bsnes-$(profile) $(DESTDIR)$(prefix)/bin/bsnes-$(profile) install -D -m 644 qt/data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png install -D -m 644 qt/data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop endif uninstall: ifeq ($(platform),x) - rm $(DESTDIR)$(prefix)/bin/bsnes + rm $(DESTDIR)$(prefix)/bin/bsnes-$(profile) rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop endif diff --git a/qt/Makefile b/qt/Makefile index f12893f3..fb4b74e0 100755 --- a/qt/Makefile +++ b/qt/Makefile @@ -26,7 +26,7 @@ else ifeq ($(platform),osx) link += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL) else ifeq ($(platform),win) ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtraster - ruby += audio.directsound + ruby += audio.directsound audio.xaudio2 ruby += input.rawinput input.directinput link += $(if $(findstring audio.openal,$(ruby)),-lopenal32) diff --git a/qt/application/application.cpp b/qt/application/application.cpp index 8fdcdc8c..7228bc46 100755 --- a/qt/application/application.cpp +++ b/qt/application/application.cpp @@ -61,6 +61,8 @@ void Application::locateFile(string &filename, bool createDataDirectory) { } int Application::main(int &argc, char **argv) { + CoInitialize(0); + app = new App(argc, argv); #if !defined(PLATFORM_WIN) //Windows port uses 256x256 icon from resource file diff --git a/qt/settings/profile.cpp b/qt/settings/profile.cpp index 4fe2705d..23b53733 100755 --- a/qt/settings/profile.cpp +++ b/qt/settings/profile.cpp @@ -16,75 +16,87 @@ ProfileSettingsWindow::ProfileSettingsWindow() { layout->addWidget(profileInfo); layout->addSpacing(Style::WidgetSpacing); - profileResearch = new QRadioButton("Research"); - profileResearch->setStyleSheet("font-weight: bold; font-size: 12pt;"); - layout->addWidget(profileResearch); + profileAccuracy = new QRadioButton("Accuracy"); + profileAccuracy->setStyleSheet( + "font-weight: bold;" + "font-size: 12pt;" + "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(255, 0, 0, 48), stop: 1 rgba(255, 0, 0, 0));" + ); + layout->addWidget(profileAccuracy); - profileResearchInfo = new QLabel( + profileAccuracyInfo = new QLabel( "System Requirements: A super-computer cooled by LN2.
" "Maximum accuracy, no matter the cost.
" - "Use this mode for development purposes only." + "Use this mode for development or research purposes." ); - profileResearchInfo->setStyleSheet("margin-left: 22px;"); - layout->addWidget(profileResearchInfo); + profileAccuracyInfo->setStyleSheet("margin-left: 22px;"); + layout->addWidget(profileAccuracyInfo); layout->addSpacing(Style::WidgetSpacing); - profileBaseline = new QRadioButton("Baseline (recommended)"); - profileBaseline->setStyleSheet("font-weight: bold; font-size: 12pt;"); - layout->addWidget(profileBaseline); + profileCompatibility = new QRadioButton("Compatibility"); + profileCompatibility->setStyleSheet( + "font-weight: bold;" + "font-size: 12pt;" + "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(0, 0, 255, 48), stop: 1 rgba(0, 0, 255, 0));" + ); + layout->addWidget(profileCompatibility); - profileBaselineInfo = new QLabel( + profileCompatibilityInfo = new QLabel( "System Requirements: Intel Core Solo or AMD Athlon 64 processor.
" "Extreme accuracy with reasonable hardware requirements in mind.
" - "Very rarely, slight graphical glitches may appear." + "Very rarely, slight graphical glitches may appear in a small number of games." ); - profileBaselineInfo->setStyleSheet("margin-left: 22px;"); - layout->addWidget(profileBaselineInfo); + profileCompatibilityInfo->setStyleSheet("margin-left: 22px;"); + layout->addWidget(profileCompatibilityInfo); layout->addSpacing(Style::WidgetSpacing); profilePerformance = new QRadioButton("Performance"); - profilePerformance->setStyleSheet("font-weight: bold; font-size: 12pt;"); + profilePerformance->setStyleSheet( + "font-weight: bold;" + "font-size: 12pt;" + "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(0, 255, 0, 48), stop: 1 rgba(0, 255, 0, 0));" + ); layout->addWidget(profilePerformance); profilePerformanceInfo = new QLabel( "System Requirements: Intel Atom, Intel Pentium IV or AMD Athlon processor.
" - "High accuracy with reasonable sacrifices for performance.
" + "High accuracy with reasonable compromises for performance.
" "Sacrifices a small degree of compatibility to run full-speed on older hardware.
" - "Use this mode only if baseline is too slow, or if you are running on battery power." + "Use this mode for slower systems, or if you are running on battery power." ); profilePerformanceInfo->setStyleSheet("margin-left: 22px;"); layout->addWidget(profilePerformanceInfo); - if(config().system.profile == "research") { - profileResearch->setChecked(true); - } else if(config().system.profile == "baseline") { - profileBaseline->setChecked(true); + if(config().system.profile == "accuracy") { + profileAccuracy->setChecked(true); + } else if(config().system.profile == "compatibility") { + profileCompatibility->setChecked(true); } else if(config().system.profile == "performance") { profilePerformance->setChecked(true); } else { - config().system.profile = "baseline"; - profileBaseline->setChecked(true); + config().system.profile = "compatibility"; + profileCompatibility->setChecked(true); QMessageBox::information(0, "First-Run Notice", "Note: bsnes contains multiple emulation profiles.

" - "If bsnes runs too slowly, you can double the speed by using the " + "If bsnes runs too slowly, you can greatly increase the speed by using the " "'Performance' profile; or if you want even more accuracy, you can use the " - "'Research' profile.

" + "'Accuracy' profile.

" "Feel free to experiment. You can select different profiles via:
" "Settings -> Configuration -> Profile" ); } - connect(profileResearch, SIGNAL(pressed()), this, SLOT(setResearchProfile())); - connect(profileBaseline, SIGNAL(pressed()), this, SLOT(setBaselineProfile())); + connect(profileAccuracy, SIGNAL(pressed()), this, SLOT(setAccuracyProfile())); + connect(profileCompatibility, SIGNAL(pressed()), this, SLOT(setCompatibilityProfile())); connect(profilePerformance, SIGNAL(pressed()), this, SLOT(setPerformanceProfile())); } -void ProfileSettingsWindow::setResearchProfile() { - config().system.profile = "research"; +void ProfileSettingsWindow::setAccuracyProfile() { + config().system.profile = "accuracy"; } -void ProfileSettingsWindow::setBaselineProfile() { - config().system.profile = "baseline"; +void ProfileSettingsWindow::setCompatibilityProfile() { + config().system.profile = "compatibility"; } void ProfileSettingsWindow::setPerformanceProfile() { diff --git a/qt/settings/profile.moc.hpp b/qt/settings/profile.moc.hpp index 16f06e53..cb156749 100755 --- a/qt/settings/profile.moc.hpp +++ b/qt/settings/profile.moc.hpp @@ -4,18 +4,18 @@ class ProfileSettingsWindow : public QWidget { public: QVBoxLayout *layout; QLabel *profileInfo; - QRadioButton *profileResearch; - QLabel *profileResearchInfo; - QRadioButton *profileBaseline; - QLabel *profileBaselineInfo; + QRadioButton *profileAccuracy; + QLabel *profileAccuracyInfo; + QRadioButton *profileCompatibility; + QLabel *profileCompatibilityInfo; QRadioButton *profilePerformance; QLabel *profilePerformanceInfo; ProfileSettingsWindow(); private slots: - void setResearchProfile(); - void setBaselineProfile(); + void setAccuracyProfile(); + void setCompatibilityProfile(); void setPerformanceProfile(); }; diff --git a/ruby/_test/cc.bat b/ruby/_test/cc.bat new file mode 100755 index 00000000..00b9e552 --- /dev/null +++ b/ruby/_test/cc.bat @@ -0,0 +1,2 @@ +@g++ -std=gnu++0x -O3 -fomit-frame-pointer -I../.. -o test test.cpp -DAUDIO_DIRECTSOUND -DAUDIO_XAUDIO2 -DINPUT_DIRECTINPUT -lole32 -luuid -ldxguid -ldsound -ldinput8 +@pause diff --git a/ruby/_test/test.cpp b/ruby/_test/test.cpp new file mode 100755 index 00000000..64778930 --- /dev/null +++ b/ruby/_test/test.cpp @@ -0,0 +1,40 @@ +#include +#include +using namespace nall; + +#include +using namespace ruby; + +#include + +int main() { + CoInitialize(0); + + audio.driver("XAudio2"); + audio.set(Audio::Handle, (uintptr_t)GetDesktopWindow()); + audio.set(Audio::Synchronize, true); + audio.set(Audio::Frequency, 44100U); + if(audio.init() == false) { + printf("Failed to initialize audio driver.\n"); + getch(); + return 0; + } + + input.driver("DirectInput"); + input.set(Input::Handle, (uintptr_t)GetDesktopWindow()); + if(input.init() == false) { + printf("Failed to initialize input driver.\n"); + getch(); + return 0; + } + + while(true) { + int16_t table[Scancode::Limit]; + input.poll(table); + for(unsigned i = 0; i < Scancode::Limit; i++) { + //if(table[i]) printf("%.4x\n", i); + } + } + + return 0; +} diff --git a/ruby/_test/test.exe b/ruby/_test/test.exe new file mode 100755 index 00000000..8032f45a Binary files /dev/null and b/ruby/_test/test.exe differ diff --git a/ruby/audio/xaudio2.cpp b/ruby/audio/xaudio2.cpp new file mode 100755 index 00000000..d6298593 --- /dev/null +++ b/ruby/audio/xaudio2.cpp @@ -0,0 +1,200 @@ +/* + audio.xaudio2 (2010-08-14) + author: OV2 +*/ + +#include "xaudio2.hpp" +#include + +namespace ruby { + +class pAudioXAudio2: public IXAudio2VoiceCallback { +public: + IXAudio2 *pXAudio2; + IXAudio2MasteringVoice* pMasterVoice; + IXAudio2SourceVoice *pSourceVoice; + + // inherited from IXAudio2VoiceCallback + STDMETHODIMP_(void) OnBufferStart(void *pBufferContext){} + STDMETHODIMP_(void) OnLoopEnd(void *pBufferContext){} + STDMETHODIMP_(void) OnStreamEnd() {} + STDMETHODIMP_(void) OnVoiceError(void *pBufferContext, HRESULT Error) {} + STDMETHODIMP_(void) OnVoiceProcessingPassEnd() {} + STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {} + + struct { + unsigned buffers; + unsigned latency; + + uint32_t *buffer; + unsigned bufferoffset; + + volatile long submitbuffers; + unsigned writebuffer; + } device; + + struct { + bool synchronize; + unsigned frequency; + unsigned latency; + } settings; + + bool cap(const string& name) { + if(name == Audio::Synchronize) return true; + if(name == Audio::Frequency) return true; + if(name == Audio::Latency) return true; + return false; + } + + any get(const string& name) { + if(name == Audio::Synchronize) return settings.synchronize; + if(name == Audio::Frequency) return settings.frequency; + if(name == Audio::Latency) return settings.latency; + return false; + } + + bool set(const string& name, const any& value) { + if(name == Audio::Synchronize) { + settings.synchronize = any_cast(value); + if(pXAudio2) clear(); + return true; + } + + if(name == Audio::Frequency) { + settings.frequency = any_cast(value); + if(pXAudio2) init(); + return true; + } + + if(name == Audio::Latency) { + settings.latency = any_cast(value); + if(pXAudio2) init(); + return true; + } + + return false; + } + + void pushbuffer(unsigned bytes,uint32_t *pAudioData) { + XAUDIO2_BUFFER xa2buffer={0}; + xa2buffer.AudioBytes=bytes; + xa2buffer.pAudioData=reinterpret_cast(pAudioData); + xa2buffer.pContext=0; + InterlockedIncrement(&device.submitbuffers); + pSourceVoice->SubmitSourceBuffer(&xa2buffer); + } + + void sample(uint16_t left, uint16_t right) { + device.buffer[device.writebuffer * device.latency + device.bufferoffset++] = left + (right << 16); + if(device.bufferoffset < device.latency) return; + device.bufferoffset = 0; + + if(device.submitbuffers == device.buffers - 1) { + if(settings.synchronize == true) { + //wait until there is at least one other free buffer for the next sample + while(device.submitbuffers == device.buffers - 1) { + //Sleep(0); + } + } else { //we need one free buffer for the next sample, so ignore the current contents + return; + } + } + + pushbuffer(device.latency * 4,device.buffer + device.writebuffer * device.latency); + + device.writebuffer = (device.writebuffer + 1) % device.buffers; + } + + void clear() { + if(!pSourceVoice) return; + pSourceVoice->Stop(0); + pSourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers + + device.writebuffer = 0; + + device.bufferoffset = 0; + if(device.buffer) memset(device.buffer, 0, device.latency * device.buffers * 4); + + pSourceVoice->Start(0); + } + + bool init() { + term(); + + device.buffers = 8; + device.latency = settings.frequency * settings.latency / device.buffers / 1000.0 + 0.5; + device.buffer = new uint32_t[device.latency * device.buffers]; + device.bufferoffset = 0; + device.submitbuffers = 0; + + HRESULT hr; + if(FAILED(hr = XAudio2Create(&pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR))) { + return false; + } + + if(FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, 2, + settings.frequency, 0, 0 , NULL))) { + return false; + } + + WAVEFORMATEX wfx; + wfx.wFormatTag = WAVE_FORMAT_PCM; + wfx.nChannels = 2; + wfx.nSamplesPerSec = settings.frequency; + wfx.nBlockAlign = 4; + wfx.wBitsPerSample = 16; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + wfx.cbSize = 0; + + if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx, + XAUDIO2_VOICE_NOSRC , XAUDIO2_DEFAULT_FREQ_RATIO, this, NULL, NULL))) { + return false; + } + + clear(); + return true; + } + + void term() { + if(pSourceVoice) { + pSourceVoice->Stop(0); + pSourceVoice->DestroyVoice(); + pSourceVoice = 0; + } + if(pMasterVoice) { + pMasterVoice->DestroyVoice(); + pMasterVoice = 0; + } + if(pXAudio2) { + pXAudio2->Release(); + pXAudio2 = NULL; + } + if(device.buffer) { + delete[] device.buffer; + device.buffer = 0; + } + } + + STDMETHODIMP_(void) OnBufferEnd(void *pBufferContext) { + InterlockedDecrement(&device.submitbuffers); + } + + pAudioXAudio2() { + pXAudio2 = 0; + pMasterVoice = 0; + pSourceVoice = 0; + + device.buffer = 0; + device.bufferoffset = 0; + device.submitbuffers = 0; + device.writebuffer = 0; + + settings.synchronize = false; + settings.frequency = 22050; + settings.latency = 120; + } +}; + +DeclareAudio(XAudio2) + +}; diff --git a/ruby/audio/xaudio2.hpp b/ruby/audio/xaudio2.hpp new file mode 100755 index 00000000..86e19471 --- /dev/null +++ b/ruby/audio/xaudio2.hpp @@ -0,0 +1,336 @@ +/* + xaudio2.hpp (2010-08-14) + author: OV2 + + ruby-specific header to provide mingw-friendly xaudio2 interfaces +*/ + +#ifndef XAUDIO2_RUBY_H +#define XAUDIO2_RUBY_H + +#include + +#define DEFINE_GUID_X(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) GUID_EXT const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} +#define DEFINE_CLSID_X(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + DEFINE_GUID_X(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8) +#define DEFINE_IID_X(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + DEFINE_GUID_X(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8) +#define X2DEFAULT(x) =x + +DEFINE_CLSID_X(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08); +DEFINE_CLSID_X(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd); +DEFINE_IID_X(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb); + +DECLARE_INTERFACE(IXAudio2Voice); + +#define XAUDIO2_COMMIT_NOW 0 +#define XAUDIO2_DEFAULT_CHANNELS 0 +#define XAUDIO2_DEFAULT_SAMPLERATE 0 +#define XAUDIO2_DEFAULT_FREQ_RATIO 4.0f +#define XAUDIO2_DEBUG_ENGINE 0x0001 +#define XAUDIO2_VOICE_NOSRC 0x0004 + +typedef struct +{ + WAVEFORMATEX Format; + union + { + WORD wValidBitsPerSample; + WORD wSamplesPerBlock; + WORD wReserved; + } Samples; + DWORD dwChannelMask; + GUID SubFormat; +} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE, *LPPWAVEFORMATEXTENSIBLE; +typedef const WAVEFORMATEXTENSIBLE* LPCWAVEFORMATEXTENSIBLE; + +typedef enum XAUDIO2_DEVICE_ROLE +{ + NotDefaultDevice = 0x0, + DefaultConsoleDevice = 0x1, + DefaultMultimediaDevice = 0x2, + DefaultCommunicationsDevice = 0x4, + DefaultGameDevice = 0x8, + GlobalDefaultDevice = 0xf, + InvalidDeviceRole = ~GlobalDefaultDevice +} XAUDIO2_DEVICE_ROLE; + +typedef struct XAUDIO2_DEVICE_DETAILS +{ + WCHAR DeviceID[256]; + WCHAR DisplayName[256]; + XAUDIO2_DEVICE_ROLE Role; + WAVEFORMATEXTENSIBLE OutputFormat; +} XAUDIO2_DEVICE_DETAILS; + +typedef struct XAUDIO2_VOICE_DETAILS +{ + UINT32 CreationFlags; + UINT32 InputChannels; + UINT32 InputSampleRate; +} XAUDIO2_VOICE_DETAILS; + +typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER +{ + Processor1 = 0x00000001, + Processor2 = 0x00000002, + Processor3 = 0x00000004, + Processor4 = 0x00000008, + Processor5 = 0x00000010, + Processor6 = 0x00000020, + Processor7 = 0x00000040, + Processor8 = 0x00000080, + Processor9 = 0x00000100, + Processor10 = 0x00000200, + Processor11 = 0x00000400, + Processor12 = 0x00000800, + Processor13 = 0x00001000, + Processor14 = 0x00002000, + Processor15 = 0x00004000, + Processor16 = 0x00008000, + Processor17 = 0x00010000, + Processor18 = 0x00020000, + Processor19 = 0x00040000, + Processor20 = 0x00080000, + Processor21 = 0x00100000, + Processor22 = 0x00200000, + Processor23 = 0x00400000, + Processor24 = 0x00800000, + Processor25 = 0x01000000, + Processor26 = 0x02000000, + Processor27 = 0x04000000, + Processor28 = 0x08000000, + Processor29 = 0x10000000, + Processor30 = 0x20000000, + Processor31 = 0x40000000, + Processor32 = 0x80000000, + XAUDIO2_ANY_PROCESSOR = 0xffffffff, + XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR +} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR; + +typedef struct XAUDIO2_VOICE_SENDS +{ + UINT32 OutputCount; + IXAudio2Voice** pOutputVoices; +} XAUDIO2_VOICE_SENDS; + +typedef struct XAUDIO2_EFFECT_DESCRIPTOR +{ + IUnknown* pEffect; + BOOL InitialState; + UINT32 OutputChannels; +} XAUDIO2_EFFECT_DESCRIPTOR; + +typedef struct XAUDIO2_EFFECT_CHAIN +{ + UINT32 EffectCount; + const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors; +} XAUDIO2_EFFECT_CHAIN; + +typedef enum XAUDIO2_FILTER_TYPE +{ + LowPassFilter, + BandPassFilter, + HighPassFilter +} XAUDIO2_FILTER_TYPE; + +typedef struct XAUDIO2_FILTER_PARAMETERS +{ + XAUDIO2_FILTER_TYPE Type; + float Frequency; + float OneOverQ; + +} XAUDIO2_FILTER_PARAMETERS; + +typedef struct XAUDIO2_BUFFER +{ + UINT32 Flags; + UINT32 AudioBytes; + const BYTE* pAudioData; + UINT32 PlayBegin; + UINT32 PlayLength; + UINT32 LoopBegin; + UINT32 LoopLength; + UINT32 LoopCount; + void* pContext; +} XAUDIO2_BUFFER; + +typedef struct XAUDIO2_BUFFER_WMA +{ + const UINT32* pDecodedPacketCumulativeBytes; + UINT32 PacketCount; +} XAUDIO2_BUFFER_WMA; + +typedef struct XAUDIO2_VOICE_STATE +{ + void* pCurrentBufferContext; + UINT32 BuffersQueued; + UINT64 SamplesPlayed; +} XAUDIO2_VOICE_STATE; + +typedef struct XAUDIO2_PERFORMANCE_DATA +{ + UINT64 AudioCyclesSinceLastQuery; + UINT64 TotalCyclesSinceLastQuery; + UINT32 MinimumCyclesPerQuantum; + UINT32 MaximumCyclesPerQuantum; + UINT32 MemoryUsageInBytes; + UINT32 CurrentLatencyInSamples; + UINT32 GlitchesSinceEngineStarted; + UINT32 ActiveSourceVoiceCount; + UINT32 TotalSourceVoiceCount; + UINT32 ActiveSubmixVoiceCount; + UINT32 TotalSubmixVoiceCount; + UINT32 ActiveXmaSourceVoices; + UINT32 ActiveXmaStreams; +} XAUDIO2_PERFORMANCE_DATA; + +typedef struct XAUDIO2_DEBUG_CONFIGURATION +{ + UINT32 TraceMask; + UINT32 BreakMask; + BOOL LogThreadID; + BOOL LogFileline; + BOOL LogFunctionName; + BOOL LogTiming; +} XAUDIO2_DEBUG_CONFIGURATION; + +DECLARE_INTERFACE(IXAudio2EngineCallback) +{ + STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE; + STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE; + STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE; +}; + +DECLARE_INTERFACE(IXAudio2VoiceCallback) +{ + STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE; + STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE; + STDMETHOD_(void, OnStreamEnd) (THIS) PURE; + STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE; + STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE; + STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE; + STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE; +}; + +DECLARE_INTERFACE(IXAudio2Voice) +{ + #define Declare_IXAudio2Voice_Methods() \ + STDMETHOD_(void, GetVoiceDetails) (THIS_ XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \ + STDMETHOD(SetOutputVoices) (THIS_ const XAUDIO2_VOICE_SENDS* pSendList) PURE; \ + STDMETHOD(SetEffectChain) (THIS_ const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \ + STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, BOOL* pEnabled) PURE; \ + STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \ + const void* pParameters, \ + UINT32 ParametersByteSize, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, void* pParameters, \ + UINT32 ParametersByteSize) PURE; \ + STDMETHOD(SetFilterParameters) (THIS_ const XAUDIO2_FILTER_PARAMETERS* pParameters, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD_(void, GetFilterParameters) (THIS_ XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \ + STDMETHOD(SetVolume) (THIS_ float Volume, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD_(void, GetVolume) (THIS_ float* pVolume) PURE; \ + STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, const float* pVolumes, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, float* pVolumes) PURE; \ + STDMETHOD(SetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + const float* pLevelMatrix, \ + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \ + STDMETHOD_(void, GetOutputMatrix) (THIS_ IXAudio2Voice* pDestinationVoice, \ + UINT32 SourceChannels, UINT32 DestinationChannels, \ + float* pLevelMatrix) PURE; \ + STDMETHOD_(void, DestroyVoice) (THIS) PURE + + Declare_IXAudio2Voice_Methods(); +}; + + +DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice) +{ + Declare_IXAudio2Voice_Methods(); +}; + +DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice) +{ + Declare_IXAudio2Voice_Methods(); +}; + +DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) +{ + Declare_IXAudio2Voice_Methods(); + STDMETHOD(Start) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + STDMETHOD(Stop) (THIS_ UINT32 Flags, UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + STDMETHOD(SubmitSourceBuffer) (THIS_ const XAUDIO2_BUFFER* pBuffer, const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE; + STDMETHOD(FlushSourceBuffers) (THIS) PURE; + STDMETHOD(Discontinuity) (THIS) PURE; + STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + STDMETHOD_(void, GetState) (THIS_ XAUDIO2_VOICE_STATE* pVoiceState) PURE; + STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio, + UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; + STDMETHOD_(void, GetFrequencyRatio) (THIS_ float* pRatio) PURE; +}; + +DECLARE_INTERFACE_(IXAudio2, IUnknown) +{ + STDMETHOD(QueryInterface) (THIS_ REFIID riid, void** ppvInterface) PURE; + STDMETHOD_(ULONG, AddRef) (THIS) PURE; + STDMETHOD_(ULONG, Release) (THIS) PURE; + STDMETHOD(GetDeviceCount) (THIS_ UINT32* pCount) PURE; + STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE; + STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE; + STDMETHOD(RegisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE; + STDMETHOD_(void, UnregisterForCallbacks) (IXAudio2EngineCallback* pCallback) PURE; + STDMETHOD(CreateSourceVoice) (THIS_ IXAudio2SourceVoice** ppSourceVoice, + const WAVEFORMATEX* pSourceFormat, + UINT32 Flags X2DEFAULT(0), + float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO), + IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL), + const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + STDMETHOD(CreateSubmixVoice) (THIS_ IXAudio2SubmixVoice** ppSubmixVoice, + UINT32 InputChannels, UINT32 InputSampleRate, + UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0), + const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL), + const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + STDMETHOD(CreateMasteringVoice) (THIS_ IXAudio2MasteringVoice** ppMasteringVoice, + UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS), + UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE), + UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0), + const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE; + STDMETHOD(StartEngine) (THIS) PURE; + STDMETHOD_(void, StopEngine) (THIS) PURE; + STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE; + STDMETHOD_(void, GetPerformanceData) (THIS_ XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE; + STDMETHOD_(void, SetDebugConfiguration) (THIS_ const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration, + void* pReserved X2DEFAULT(NULL)) PURE; +}; + +__inline HRESULT XAudio2Create(IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0), + XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) +{ + IXAudio2* pXAudio2; + HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2, + NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2); + if (SUCCEEDED(hr)) + { + hr = pXAudio2->Initialize(Flags, XAudio2Processor); + if (SUCCEEDED(hr)) + { + *ppXAudio2 = pXAudio2; + } + else + { + pXAudio2->Release(); + } + } + return hr; +} +#endif diff --git a/ruby/input/directinput.cpp b/ruby/input/directinput.cpp index cb0da3c2..6db107b2 100755 --- a/ruby/input/directinput.cpp +++ b/ruby/input/directinput.cpp @@ -139,16 +139,16 @@ public: key(Keyboard::Period ) = (bool)(state[0x34] & 0x80); key(Keyboard::Slash ) = (bool)(state[0x35] & 0x80); - key(Keyboard::Keypad0) = (bool)(state[0x4f] & 0x80); - key(Keyboard::Keypad1) = (bool)(state[0x50] & 0x80); - key(Keyboard::Keypad2) = (bool)(state[0x51] & 0x80); - key(Keyboard::Keypad3) = (bool)(state[0x4b] & 0x80); - key(Keyboard::Keypad4) = (bool)(state[0x4c] & 0x80); - key(Keyboard::Keypad5) = (bool)(state[0x4d] & 0x80); - key(Keyboard::Keypad6) = (bool)(state[0x47] & 0x80); - key(Keyboard::Keypad7) = (bool)(state[0x48] & 0x80); - key(Keyboard::Keypad8) = (bool)(state[0x49] & 0x80); - key(Keyboard::Keypad9) = (bool)(state[0x52] & 0x80); + key(Keyboard::Keypad1) = (bool)(state[0x4f] & 0x80); + key(Keyboard::Keypad2) = (bool)(state[0x50] & 0x80); + key(Keyboard::Keypad3) = (bool)(state[0x51] & 0x80); + key(Keyboard::Keypad4) = (bool)(state[0x4b] & 0x80); + key(Keyboard::Keypad5) = (bool)(state[0x4c] & 0x80); + key(Keyboard::Keypad6) = (bool)(state[0x4d] & 0x80); + key(Keyboard::Keypad7) = (bool)(state[0x47] & 0x80); + key(Keyboard::Keypad8) = (bool)(state[0x48] & 0x80); + key(Keyboard::Keypad9) = (bool)(state[0x49] & 0x80); + key(Keyboard::Keypad0) = (bool)(state[0x52] & 0x80); key(Keyboard::Point ) = (bool)(state[0x53] & 0x80); key(Keyboard::Add ) = (bool)(state[0x4e] & 0x80); diff --git a/ruby/ruby.cpp b/ruby/ruby.cpp index 52395973..b52c63b1 100755 --- a/ruby/ruby.cpp +++ b/ruby/ruby.cpp @@ -194,6 +194,10 @@ void AudioInterface::driver(const char *driver) { else if(!strcmp(driver, "PulseAudioSimple")) p = new AudioPulseAudioSimple(); #endif + #ifdef AUDIO_XAUDIO2 + else if(!strcmp(driver, "XAudio2")) p = new AudioXAudio2(); + #endif + else p = new Audio(); } @@ -201,6 +205,8 @@ void AudioInterface::driver(const char *driver) { const char* AudioInterface::default_driver() { #if defined(AUDIO_DIRECTSOUND) return "DirectSound"; + #elif defined(AUDIO_XAUDIO2) + return "XAudio2"; #elif defined(AUDIO_ALSA) return "ALSA"; #elif defined(AUDIO_OPENAL) @@ -228,6 +234,10 @@ const char* AudioInterface::driver_list() { "DirectSound;" #endif + #if defined(AUDIO_XAUDIO2) + "XAudio2;" + #endif + //Linux #if defined(AUDIO_ALSA) @@ -298,10 +308,10 @@ void InputInterface::driver(const char *driver) { //select the *safest* available driver, not the fastest const char* InputInterface::default_driver() { - #if defined(INPUT_RAWINPUT) - return "RawInput"; - #elif defined(INPUT_DIRECTINPUT) + #if defined(INPUT_DIRECTINPUT) return "DirectInput"; + #elif defined(INPUT_RAWINPUT) + return "RawInput"; #elif defined(INPUT_SDL) return "SDL"; #elif defined(INPUT_X) diff --git a/ruby/ruby_impl.cpp b/ruby/ruby_impl.cpp index c2bdc2d1..4b7049e2 100755 --- a/ruby/ruby_impl.cpp +++ b/ruby/ruby_impl.cpp @@ -133,6 +133,10 @@ #include #endif +#ifdef AUDIO_XAUDIO2 + #include +#endif + /* Input */ #define DeclareInput(Name) \ diff --git a/snes/Makefile b/snes/Makefile index 06f9f91f..2a4b7fe3 100755 --- a/snes/Makefile +++ b/snes/Makefile @@ -10,14 +10,14 @@ snes_objects += snes-obc1 snes-st0010 snes-st0011 snes-st0018 snes_objects += snes-msu1 snes-serial objects += $(snes_objects) -ifeq ($(profile),research) - flags += -DPROFILE_RESEARCH +ifeq ($(profile),accuracy) + flags += -DPROFILE_ACCURACY snescpu := $(snes)/cpu snessmp := $(snes)/smp snesdsp := $(snes)/dsp snesppu := $(snes)/ppu -else ifeq ($(profile),baseline) - flags += -DPROFILE_BASELINE +else ifeq ($(profile),compatibility) + flags += -DPROFILE_COMPATIBILITY snescpu := $(snes)/cpu snessmp := $(snes)/smp snesdsp := $(snes)/fast/dsp diff --git a/snes/profile-research.hpp b/snes/profile-accuracy.hpp similarity index 54% rename from snes/profile-research.hpp rename to snes/profile-accuracy.hpp index ca1b8d75..006968cb 100755 --- a/snes/profile-research.hpp +++ b/snes/profile-accuracy.hpp @@ -1,6 +1,5 @@ namespace Info { - static const char Profile[] = "Research"; - static const char ProfileName[] = "Superfluous"; + static const char Profile[] = "Accuracy"; } #include diff --git a/snes/profile-baseline.hpp b/snes/profile-compatibility.hpp similarity index 55% rename from snes/profile-baseline.hpp rename to snes/profile-compatibility.hpp index 1ee4d403..2f551138 100755 --- a/snes/profile-baseline.hpp +++ b/snes/profile-compatibility.hpp @@ -1,6 +1,5 @@ namespace Info { - static const char Profile[] = "Baseline"; - static const char ProfileName[] = "Supersedence"; + static const char Profile[] = "Compatibility"; } #include diff --git a/snes/profile-performance.hpp b/snes/profile-performance.hpp index a0040af0..d43557d6 100755 --- a/snes/profile-performance.hpp +++ b/snes/profile-performance.hpp @@ -1,6 +1,5 @@ namespace Info { static const char Profile[] = "Performance"; - static const char ProfileName[] = "Supersonic"; } #include diff --git a/snes/snes.hpp b/snes/snes.hpp index 0ff0f13c..04c1a35c 100755 --- a/snes/snes.hpp +++ b/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "067.21"; + static const char Version[] = "067.22"; static const unsigned SerializerVersion = 12; } } @@ -76,10 +76,10 @@ namespace SNES { #include #include - #if defined(PROFILE_RESEARCH) - #include "profile-research.hpp" - #elif defined(PROFILE_BASELINE) - #include "profile-baseline.hpp" + #if defined(PROFILE_ACCURACY) + #include "profile-accuracy.hpp" + #elif defined(PROFILE_COMPATIBILITY) + #include "profile-compatibility.hpp" #elif defined(PROFILE_PERFORMANCE) #include "profile-performance.hpp" #endif