mirror of https://github.com/bsnes-emu/bsnes.git
Update to v103r14 release.
byuu says: Changelog: - tomoko: by popular choice, default to adaptive mode on new installs - hiro/windows: fix bug that was preventing the escape key from closing some dialog windows - nall/registry: use "\\\\" as separator instead of "/" ... because some registry keys contain "/" in them >_> - ruby: add ASIO driver stub (so far it can only initialize and grab the driver name/version information)
This commit is contained in:
parent
ed5ec58595
commit
17697317d4
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "103.13";
|
||||
static const string Version = "103.14";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -19,7 +19,7 @@ ui_objects += $(if $(call streq,$(platform),windows),ui-resource)
|
|||
# platform
|
||||
ifeq ($(platform),windows)
|
||||
ruby += video.direct3d video.wgl video.directdraw video.gdi
|
||||
ruby += audio.wasapi audio.xaudio2 audio.directsound
|
||||
ruby += audio.asio audio.wasapi audio.xaudio2 audio.directsound
|
||||
ruby += input.windows
|
||||
else ifeq ($(platform),macosx)
|
||||
ruby += video.cgl
|
||||
|
|
|
@ -30,7 +30,7 @@ Settings::Settings() {
|
|||
|
||||
set("Video/Windowed/AspectCorrection", true);
|
||||
set("Video/Windowed/IntegralScaling", true);
|
||||
set("Video/Windowed/Adaptive", false);
|
||||
set("Video/Windowed/Adaptive", true);
|
||||
set("Video/Windowed/Scale", "Small");
|
||||
set("Video/Windowed/Scale/Small", "640x480");
|
||||
set("Video/Windowed/Scale/Medium", "960x720");
|
||||
|
|
|
@ -142,7 +142,10 @@ static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
auto object = (mObject*)GetWindowLongPtr(info.hwndFocus, GWLP_USERDATA);
|
||||
if(!object) return false;
|
||||
|
||||
if(auto window = dynamic_cast<mWindow*>(object)) {
|
||||
auto objectWindow = (mObject*)GetWindowLongPtr(GetAncestor(info.hwndFocus, GA_ROOT), GWLP_USERDATA);
|
||||
if(!objectWindow) return false;
|
||||
|
||||
if(auto window = dynamic_cast<mWindow*>(objectWindow)) {
|
||||
if(auto self = window->self()) {
|
||||
if(!self->_modalityDisabled()) {
|
||||
if(auto code = pKeyboard::_translate(wparam, lparam)) {
|
||||
|
@ -158,7 +161,6 @@ static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(auto window = object->parentWindow(true)) {
|
||||
|
@ -218,7 +220,6 @@ static auto Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
}
|
||||
}
|
||||
CloseClipboard();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -41,8 +41,8 @@ static auto BrowserWindow_fileDialog(bool save, BrowserWindow::State& state) ->
|
|||
if(path) {
|
||||
//clear COMDLG32 MRU (most recently used) file list
|
||||
//this is required in order for lpstrInitialDir to be honored in Windows 7 and above
|
||||
registry::remove("HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/LastVisitedPidlMRU/");
|
||||
registry::remove("HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/OpenSavePidlMRU/");
|
||||
registry::remove("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU\\");
|
||||
registry::remove("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\OpenSavePidlMRU\\");
|
||||
}
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace nall {
|
|||
|
||||
struct registry {
|
||||
static auto exists(const string& name) -> bool {
|
||||
auto part = name.split("/");
|
||||
auto part = name.split("\\");
|
||||
HKEY handle, rootKey = root(part.takeLeft());
|
||||
string node = part.takeRight();
|
||||
string path = part.merge("\\");
|
||||
|
@ -39,7 +39,7 @@ struct registry {
|
|||
}
|
||||
|
||||
static auto read(const string& name) -> string {
|
||||
auto part = name.split("/");
|
||||
auto part = name.split("\\");
|
||||
HKEY handle, rootKey = root(part.takeLeft());
|
||||
string node = part.takeRight();
|
||||
string path = part.merge("\\");
|
||||
|
@ -54,7 +54,7 @@ struct registry {
|
|||
}
|
||||
|
||||
static auto write(const string& name, const string& data = "") -> void {
|
||||
auto part = name.split("/");
|
||||
auto part = name.split("\\");
|
||||
HKEY handle, rootKey = root(part.takeLeft());
|
||||
string node = part.takeRight(), path;
|
||||
DWORD disposition;
|
||||
|
@ -71,7 +71,7 @@ struct registry {
|
|||
}
|
||||
|
||||
static auto remove(const string& name) -> bool {
|
||||
auto part = name.split("/");
|
||||
auto part = name.split("\\");
|
||||
HKEY rootKey = root(part.takeLeft());
|
||||
string node = part.takeRight();
|
||||
string path = part.merge("\\");
|
||||
|
@ -81,7 +81,7 @@ struct registry {
|
|||
|
||||
static auto contents(const string& name) -> string_vector {
|
||||
string_vector result;
|
||||
auto part = name.split("/");
|
||||
auto part = name.split("\\");
|
||||
HKEY handle, rootKey = root(part.takeLeft());
|
||||
part.removeRight();
|
||||
string path = part.merge("\\");
|
||||
|
@ -92,7 +92,7 @@ struct registry {
|
|||
wchar_t name[NWR_SIZE] = L"";
|
||||
DWORD size = NWR_SIZE * sizeof(wchar_t);
|
||||
RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr);
|
||||
result.append(string{(const char*)utf8_t(name), "/"});
|
||||
result.append(string{(const char*)utf8_t(name), "\\"});
|
||||
}
|
||||
for(uint n = 0; n < nodes; n++) {
|
||||
wchar_t name[NWR_SIZE] = L"";
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
#include "asio.hpp"
|
||||
|
||||
struct AudioASIO : Audio {
|
||||
~AudioASIO() { term(); }
|
||||
|
||||
struct Settings {
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = true;
|
||||
uint frequency = 48000;
|
||||
} settings;
|
||||
|
||||
struct Driver {
|
||||
string name;
|
||||
string classID;
|
||||
};
|
||||
vector<Driver> drivers;
|
||||
|
||||
Driver driver;
|
||||
IASIO* device = nullptr;
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Audio::Handle) return true;
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Audio::Handle) return (uintptr)settings.handle;
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Audio::Handle && value.is<uintptr>()) {
|
||||
settings.handle = (HWND)value.get<uintptr>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Synchronize && value.is<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Frequency && value.is<uint>()) {
|
||||
settings.frequency = value.get<uint>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto sample(int16_t left, int16_t right) -> void {
|
||||
}
|
||||
|
||||
auto clear() -> void {
|
||||
}
|
||||
|
||||
auto init() -> bool {
|
||||
//enumerate available ASIO drivers from the registry
|
||||
for(auto candidate : registry::contents("HKLM\\SOFTWARE\\ASIO\\")) {
|
||||
if(auto classID = registry::read({"HKLM\\SOFTWARE\\ASIO\\", candidate, "CLSID"})) {
|
||||
drivers.append({candidate.trimRight("\\", 1L), classID});
|
||||
}
|
||||
}
|
||||
if(!drivers) return false;
|
||||
|
||||
//default to first driver for now
|
||||
driver = drivers[0];
|
||||
|
||||
CLSID classID;
|
||||
if(CLSIDFromString((LPOLESTR)utf16_t(driver.classID), (LPCLSID)&classID) != S_OK) return false;
|
||||
if(CoCreateInstance(classID, 0, CLSCTX_INPROC_SERVER, classID, (void**)&device) != S_OK) return false;
|
||||
|
||||
if(!device->init((void*)settings.handle)) return false;
|
||||
|
||||
//temporary debugging information
|
||||
char driverName[4096] = {0};
|
||||
device->getDriverName(driverName);
|
||||
print("Driver: ", driverName, "\n");
|
||||
print("Version: ", device->getDriverVersion(), "\n");
|
||||
print("---\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto term() -> void {
|
||||
}
|
||||
};
|
|
@ -0,0 +1,171 @@
|
|||
using ASIOError = long;
|
||||
enum : long {
|
||||
ASE_OK = 0,
|
||||
ASE_SUCCESS = 0x3f4847a0,
|
||||
ASE_NotPresent = -1000,
|
||||
ASE_HWMalfunction,
|
||||
ASE_InvalidParameter,
|
||||
ASE_InvalidMode,
|
||||
ASE_SPNotAdvancing,
|
||||
ASE_NoClock,
|
||||
ASE_NoMemory,
|
||||
};
|
||||
|
||||
using ASIOBool = long;
|
||||
enum : long {
|
||||
ASIOFalse = 0,
|
||||
ASIOTrue = 1,
|
||||
};
|
||||
|
||||
using ASIOSampleRate = double;
|
||||
using ASIOSamples = long long int;
|
||||
using ASIOTimeStamp = long long int;
|
||||
|
||||
using ASIOSampleType = long;
|
||||
enum : long {
|
||||
ASIOSTInt16MSB = 0,
|
||||
ASIOSTInt24MSB = 1,
|
||||
ASIOSTInt32MSB = 2,
|
||||
ASIOSTFloat32MSB = 3,
|
||||
ASIOSTFloat64MSB = 4,
|
||||
|
||||
ASIOSTInt32MSB16 = 8,
|
||||
ASIOSTInt32MSB18 = 9,
|
||||
ASIOSTInt32MSB20 = 10,
|
||||
ASIOSTInt32MSB24 = 11,
|
||||
|
||||
ASIOSTInt16LSB = 16,
|
||||
ASIOSTInt24LSB = 17,
|
||||
ASIOSTInt32LSB = 18,
|
||||
ASIOSTFloat32LSB = 19,
|
||||
ASIOSTFloat64LSB = 20,
|
||||
|
||||
ASIOSTInt32LSB16 = 24,
|
||||
ASIOSTInt32LSB18 = 25,
|
||||
ASIOSTInt32LSB20 = 26,
|
||||
ASIOSTInt32LSB24 = 27,
|
||||
|
||||
ASIOSTDSDInt8LSB1 = 32,
|
||||
ASIOSTDSDInt8MSB1 = 33,
|
||||
ASIOSTDSDInt8NER8 = 40,
|
||||
|
||||
ASIOSTLastEntry,
|
||||
};
|
||||
|
||||
struct ASIODriverInfo {
|
||||
long asioVersion;
|
||||
long driverVersion;
|
||||
char name[32];
|
||||
char errorMessage[124];
|
||||
void* sysRef;
|
||||
};
|
||||
|
||||
struct ASIOBufferInfo {
|
||||
ASIOBool isInput;
|
||||
long channelNum;
|
||||
void* buffers[2];
|
||||
};
|
||||
|
||||
struct ASIOChannelInfo {
|
||||
long channel;
|
||||
ASIOBool isInput;
|
||||
ASIOBool isActive;
|
||||
long channelGroup;
|
||||
ASIOSampleType type;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct ASIOClockSource {
|
||||
long index;
|
||||
long associatedChannel;
|
||||
long associatedGroup;
|
||||
ASIOBool isCurrentSource;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct ASIOTimeInfo {
|
||||
double speed;
|
||||
ASIOTimeStamp systemTime;
|
||||
ASIOSamples samplePosition;
|
||||
ASIOSampleRate sampleRate;
|
||||
unsigned long flags;
|
||||
char reserved[12];
|
||||
};
|
||||
enum : unsigned long {
|
||||
kSystemTimeValid = 1 << 0,
|
||||
kSamplePositionValid = 1 << 1,
|
||||
kSampleRateValid = 1 << 2,
|
||||
kSpeedValid = 1 << 3,
|
||||
kSampleRateChanged = 1 << 4,
|
||||
kClockSourceChanged = 1 << 5,
|
||||
};
|
||||
|
||||
struct ASIOTimeCode {
|
||||
double speed;
|
||||
ASIOSamples timeCodeSamples;
|
||||
unsigned long flags;
|
||||
char future[64];
|
||||
};
|
||||
enum : unsigned long {
|
||||
kTcValid = 1 << 0,
|
||||
kTcRunning = 1 << 1,
|
||||
kTcReverse = 1 << 2,
|
||||
kTcOnspeed = 1 << 3,
|
||||
kTcStill = 1 << 4,
|
||||
kTcSpeedValid = 1 << 8,
|
||||
};
|
||||
|
||||
struct ASIOTime {
|
||||
long reserved[4];
|
||||
ASIOTimeInfo timeInfo;
|
||||
ASIOTimeCode timeCode;
|
||||
};
|
||||
|
||||
struct ASIOCallbacks {
|
||||
auto (*bufferSwitch)(long doubleBufferIndex, ASIOBool directProcess) -> void;
|
||||
auto (*sampleRateDidChange)(ASIOSampleRate sRate) -> void;
|
||||
auto (*asioMessage)(long selector, long value, void* message, double* opt) -> long;
|
||||
auto (*bufferSwitchTimeInfo)(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess) -> ASIOTime*;
|
||||
};
|
||||
enum : long {
|
||||
kAsioSelectorSupported = 1,
|
||||
kAsioEngineVersion,
|
||||
kAsioResetRequest,
|
||||
kAsioBufferSizeChange,
|
||||
kAsioResyncRequest,
|
||||
kAsioLatenciesChanged,
|
||||
kAsioSupportsTimeInfo,
|
||||
kAsioSupportsTimeCode,
|
||||
kAsioMMCCommand,
|
||||
kAsioSupportsInputMonitor,
|
||||
kAsioSupportsInputGain,
|
||||
kAsioSupportsInputMeter,
|
||||
kAsioSupportsOutputGain,
|
||||
kAsioSupportsOutputMeter,
|
||||
kAsioOverload,
|
||||
kAsioNumMessageSelectors,
|
||||
};
|
||||
|
||||
struct IASIO : public IUnknown {
|
||||
virtual auto init(void* sysHandle) -> ASIOBool;
|
||||
virtual auto getDriverName(char* name) -> void;
|
||||
virtual auto getDriverVersion() -> long;
|
||||
virtual auto getErrorMessage(char* error) -> void;
|
||||
virtual auto start() -> ASIOError;
|
||||
virtual auto stop() -> ASIOError;
|
||||
virtual auto getChannels(long* numInputChannels, long* numOutputChannels) -> ASIOError = 0;
|
||||
virtual auto getLatencies(long* inputLatency, long* outputLatency) -> ASIOError = 0;
|
||||
virtual auto getBufferSize(long* minSize, long* maxSize, long* preferredSize, long* granularity) -> ASIOError = 0;
|
||||
virtual auto canSampleRate(ASIOSampleRate sampleRate) -> ASIOError = 0;
|
||||
virtual auto getSampleRate(ASIOSampleRate* sampleRate) -> ASIOError = 0;
|
||||
virtual auto setSampleRate(ASIOSampleRate sampleRate) -> ASIOError = 0;
|
||||
virtual auto getClockSources(ASIOClockSource* clocks, long* numSources) -> ASIOError = 0;
|
||||
virtual auto setClockSource(long reference) -> ASIOError = 0;
|
||||
virtual auto getSamplePosition(ASIOSamples* sPos, ASIOTimeStamp* tStamp) -> ASIOError = 0;
|
||||
virtual auto getChannelInfo(ASIOChannelInfo* info) -> ASIOError = 0;
|
||||
virtual auto createBuffers(ASIOBufferInfo* bufferInfos, long numChannels, long bufferSize, ASIOCallbacks* callbacks) -> ASIOError = 0;
|
||||
virtual auto disposeBuffers() -> ASIOError = 0;
|
||||
virtual auto controlPanel() -> ASIOError = 0;
|
||||
virtual auto future(long selector, void* opt) -> ASIOError = 0;
|
||||
virtual auto outputReady() -> ASIOError = 0;
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
#include <dsound.h>
|
||||
|
||||
struct AudioDS : Audio {
|
||||
~AudioDS() { term(); }
|
||||
struct AudioDirectSound : Audio {
|
||||
~AudioDirectSound() { term(); }
|
||||
|
||||
LPDIRECTSOUND ds = nullptr;
|
||||
LPDIRECTSOUNDBUFFER dsb_p = nullptr;
|
||||
|
|
|
@ -238,6 +238,10 @@ auto Video::availableDrivers() -> string_vector {
|
|||
#include <ruby/audio/ao.cpp>
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
#include <ruby/audio/asio.cpp>
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_DIRECTSOUND)
|
||||
#include <ruby/audio/directsound.cpp>
|
||||
#endif
|
||||
|
@ -286,8 +290,12 @@ auto Audio::create(const string& driver) -> Audio* {
|
|||
if(driver == "libao") return new AudioAO;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
if(driver == "ASIO") return new AudioASIO;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_DIRECTSOUND)
|
||||
if(driver == "DirectSound") return new AudioDS;
|
||||
if(driver == "DirectSound") return new AudioDirectSound;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_OPENAL)
|
||||
|
@ -318,7 +326,9 @@ auto Audio::create(const string& driver) -> Audio* {
|
|||
}
|
||||
|
||||
auto Audio::optimalDriver() -> string {
|
||||
#if defined(AUDIO_WASAPI)
|
||||
#if defined(AUDIO_ASIO)
|
||||
return "ASIO";
|
||||
#elif defined(AUDIO_WASAPI)
|
||||
return "WASAPI";
|
||||
#elif defined(AUDIO_XAUDIO2)
|
||||
return "XAudio2";
|
||||
|
@ -360,6 +370,8 @@ auto Audio::safestDriver() -> string {
|
|||
return "PulseAudioSimple";
|
||||
#elif defined(AUDIO_AO)
|
||||
return "libao";
|
||||
#elif defined(AUDIO_ASIO)
|
||||
return "ASIO";
|
||||
#else
|
||||
return "None";
|
||||
#endif
|
||||
|
@ -368,6 +380,10 @@ auto Audio::safestDriver() -> string {
|
|||
auto Audio::availableDrivers() -> string_vector {
|
||||
return {
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
"ASIO",
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_WASAPI)
|
||||
"WASAPI",
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue