Update to v103r15 release.

byuu says:

Changelog:

  - ruby: rewrote the API interfaces for Video, Audio, Input
  - ruby/audio: can now select the number of output channels (not useful
    to higan, sorry)
  - ruby/asio: various improvements
  - tomoko: audio settings panel can now select separate audio devices
    (for ASIO, OSS so far)
  - tomoko: audio settings panel frequency and latency lists are
    dynamically populated now

Note: due to the ruby API rewrite, most drivers will not compile. Right
now, the following work:

  - video: Direct3D, XShm
  - audio: ASIO, OSS
  - input: Windows, SDL, Xlib

It takes a really long time to rewrite these (six hours to do the
above), so it's going to be a while before we're back at 100%
functionality again.

Errata:

  - ASIO needs device(), setDevice()
  - need to call setDevice() at program startup to populate
    frequency/latency settings properly
  - changing the device and/or frequency needs to update the emulator
    resampler rates

The really hard part is going to be the last one: the only way to change
the emulator frequency is to flush all the audio streams and then
recompute all the coefficients for the resamplers. If this is called
during emulation, all audio streams will be erased and thus no sound
will be output. I'll most likely be forced to simply ignore
device/frequency changes until the user loads another game. It is at
least possible to toggle the latency dynamically.
This commit is contained in:
Tim Allen
2017-07-17 15:11:18 +10:00
parent 17697317d4
commit 4129630d97
29 changed files with 998 additions and 886 deletions

View File

@@ -86,7 +86,8 @@ struct InputJoypadDirectInput {
return false;
}
auto init(uintptr_t handle, LPDIRECTINPUT8 context, bool xinputAvailable) -> bool {
auto initialize(uintptr handle, LPDIRECTINPUT8 context, bool xinputAvailable) -> bool {
if(!handle) return false;
this->handle = handle;
this->context = context;
this->xinputAvailable = xinputAvailable;
@@ -94,7 +95,7 @@ struct InputJoypadDirectInput {
return true;
}
auto term() -> void {
auto terminate() -> void {
for(auto& jp : joypads) {
jp.device->Unacquire();
if(jp.effect) jp.effect->Release();

View File

@@ -42,7 +42,7 @@ struct InputJoypadSDL {
}
}
auto init() -> bool {
auto initialize() -> bool {
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
SDL_JoystickEventState(SDL_IGNORE);
@@ -67,7 +67,7 @@ struct InputJoypadSDL {
return true;
}
auto term() -> void {
auto terminate() -> void {
for(auto& jp : joypads) {
SDL_JoystickClose(jp.handle);
}

View File

@@ -103,7 +103,7 @@ struct InputJoypadXInput {
return false;
}
auto init() -> bool {
auto initialize() -> bool {
if(!libxinput) libxinput = LoadLibraryA("xinput1_3.dll");
if(!libxinput) return false;
@@ -112,7 +112,7 @@ struct InputJoypadXInput {
XInputGetStateEx = (pXInputGetStateEx)GetProcAddress(libxinput, oXInputGetStateEx);
XInputSetState = (pXInputSetState)GetProcAddress(libxinput, oXInputSetState);
if(!XInputGetStateEx) XInputGetStateEx = (pXInputGetStateEx)GetProcAddress(libxinput, oXInputGetState);
if(!XInputGetStateEx || !XInputSetState) return term(), false;
if(!XInputGetStateEx || !XInputSetState) return terminate(), false;
//XInput supports a maximum of four controllers
//add all four to devices list now. If they are not connected, they will not show up in poll() results
@@ -151,7 +151,7 @@ struct InputJoypadXInput {
return true;
}
auto term() -> void {
auto terminate() -> void {
if(!libxinput) return;
FreeLibrary(libxinput);

View File

@@ -39,7 +39,7 @@ struct InputKeyboardRawInput {
devices.append(kb.hid);
}
auto init() -> bool {
auto initialize() -> bool {
rawinput.updateKeyboard = {&InputKeyboardRawInput::update, this};
//Pause sends 0x001d,4 + 0x0045,0; NumLock sends only 0x0045,0
@@ -170,7 +170,7 @@ struct InputKeyboardRawInput {
return true;
}
auto term() -> void {
auto terminate() -> void {
rawinput.updateKeyboard.reset();
}
};

View File

@@ -36,7 +36,7 @@ struct InputKeyboardXlib {
devices.append(hid);
}
auto init() -> bool {
auto initialize() -> bool {
display = XOpenDisplay(0);
keys.append({"Escape", XK_Escape});
@@ -163,7 +163,7 @@ struct InputKeyboardXlib {
return true;
}
auto term() -> void {
auto terminate() -> void {
if(display) {
XCloseDisplay(display);
display = nullptr;

View File

@@ -5,7 +5,7 @@ struct InputMouseRawInput {
Input& input;
InputMouseRawInput(Input& input) : input(input) {}
uintptr_t handle = 0;
uintptr handle = 0;
bool mouseAcquired = false;
struct Mouse {
@@ -17,6 +17,17 @@ struct InputMouseRawInput {
bool buttons[5] = {0};
} ms;
auto acquired() -> bool {
if(mouseAcquired) {
SetFocus((HWND)handle);
SetCapture((HWND)handle);
RECT rc;
GetWindowRect((HWND)handle, &rc);
ClipCursor(&rc);
}
return GetCapture() == (HWND)handle;
}
auto acquire() -> bool {
if(!mouseAcquired) {
mouseAcquired = true;
@@ -35,17 +46,6 @@ struct InputMouseRawInput {
return true;
}
auto acquired() -> bool {
if(mouseAcquired) {
SetFocus((HWND)handle);
SetCapture((HWND)handle);
RECT rc;
GetWindowRect((HWND)handle, &rc);
ClipCursor(&rc);
}
return GetCapture() == (HWND)handle;
}
auto update(RAWINPUT* input) -> void {
if((input->data.mouse.usFlags & 1) == MOUSE_MOVE_RELATIVE) {
ms.relativeX += input->data.mouse.lLastX;
@@ -95,7 +95,8 @@ struct InputMouseRawInput {
devices.append(ms.hid);
}
auto init(uintptr_t handle) -> bool {
auto initialize(uintptr handle) -> bool {
if(!handle) return false;
this->handle = handle;
ms.hid->setID(2);
@@ -114,7 +115,7 @@ struct InputMouseRawInput {
return true;
}
auto term() -> void {
auto terminate() -> void {
rawinput.updateMouse.reset();
release();
}

View File

@@ -7,11 +7,11 @@ struct InputMouseXlib {
shared_pointer<HID::Mouse> hid{new HID::Mouse};
uintptr_t handle = 0;
uintptr handle = 0;
Display* display = nullptr;
Window rootWindow;
Cursor invisibleCursor;
Window rootWindow = 0;
Cursor invisibleCursor = 0;
unsigned screenWidth = 0;
unsigned screenHeight = 0;
@@ -24,6 +24,10 @@ struct InputMouseXlib {
unsigned relativeY = 0;
} ms;
auto acquired() -> bool {
return ms.acquired;
}
auto acquire() -> bool {
if(acquired()) return true;
@@ -53,10 +57,6 @@ struct InputMouseXlib {
return true;
}
auto acquired() -> bool {
return ms.acquired;
}
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
@@ -103,7 +103,10 @@ struct InputMouseXlib {
devices.append(hid);
}
auto init(uintptr_t handle) -> bool {
auto initialize(uintptr handle) -> bool {
terminate();
if(!handle) return false;
this->handle = handle;
display = XOpenDisplay(0);
rootWindow = DefaultRootWindow(display);
@@ -143,10 +146,16 @@ struct InputMouseXlib {
return true;
}
auto term() -> void {
auto terminate() -> void {
release();
XFreeCursor(display, invisibleCursor);
XCloseDisplay(display);
if(invisibleCursor) {
XFreeCursor(display, invisibleCursor);
invisibleCursor = 0;
}
if(display) {
XCloseDisplay(display);
display = nullptr;
}
}
};

View File

@@ -7,55 +7,36 @@
#include "joypad/sdl.cpp"
struct InputSDL : Input {
InputKeyboardXlib xlibKeyboard;
InputMouseXlib xlibMouse;
InputJoypadSDL sdl;
InputSDL() : xlibKeyboard(*this), xlibMouse(*this), sdl(*this) {}
~InputSDL() { term(); }
InputSDL() : _keyboard(*this), _mouse(*this), _joypad(*this) { initialize(); }
~InputSDL() { terminate(); }
struct Settings {
uintptr_t handle = 0;
} settings;
auto ready() -> bool { return _ready; }
auto cap(const string& name) -> bool {
if(name == Input::Handle) return true;
if(name == Input::KeyboardSupport) return true;
if(name == Input::MouseSupport) return true;
if(name == Input::JoypadSupport) return true;
return false;
}
auto context() -> uintptr { return _context; }
auto get(const string& name) -> any {
if(name == Input::Handle) return (uintptr_t)settings.handle;
return {};
}
auto set(const string& name, const any& value) -> bool {
if(name == Input::Handle && value.is<uintptr_t>()) {
settings.handle = value.get<uintptr_t>();
return true;
}
return false;
}
auto acquire() -> bool {
return xlibMouse.acquire();
}
auto release() -> bool {
return xlibMouse.release();
auto setContext(uintptr context) -> bool {
if(_context == context) return true;
_context = context;
return initialize();
}
auto acquired() -> bool {
return xlibMouse.acquired();
return _mouse.acquired();
}
auto acquire() -> bool {
return _mouse.acquire();
}
auto release() -> bool {
return _mouse.release();
}
auto poll() -> vector<shared_pointer<HID::Device>> {
vector<shared_pointer<HID::Device>> devices;
xlibKeyboard.poll(devices);
xlibMouse.poll(devices);
sdl.poll(devices);
_keyboard.poll(devices);
_mouse.poll(devices);
_joypad.poll(devices);
return devices;
}
@@ -63,16 +44,26 @@ struct InputSDL : Input {
return false;
}
auto init() -> bool {
if(!xlibKeyboard.init()) return false;
if(!xlibMouse.init(settings.handle)) return false;
if(!sdl.init()) return false;
return true;
private:
auto initialize() -> bool {
terminate();
if(!_keyboard.initialize()) return false;
if(!_mouse.initialize(_context)) return false;
if(!_joypad.initialize()) return false;
return _ready = true;
}
auto term() -> void {
xlibKeyboard.term();
xlibMouse.term();
sdl.term();
auto terminate() -> void {
_ready = false;
_keyboard.terminate();
_mouse.terminate();
_joypad.terminate();
}
bool _ready = false;
uintptr _context = 0;
InputKeyboardXlib _keyboard;
InputMouseXlib _mouse;
InputJoypadSDL _joypad;
};

View File

@@ -9,97 +9,93 @@
#include "joypad/directinput.cpp"
struct InputWindows : Input {
InputKeyboardRawInput rawinputKeyboard;
InputMouseRawInput rawinputMouse;
InputJoypadXInput xinput;
InputJoypadDirectInput directinput;
InputWindows() : rawinputKeyboard(*this), rawinputMouse(*this), xinput(*this), directinput(*this) {}
~InputWindows() { term(); }
InputWindows() : _keyboard(*this), _mouse(*this), _joypadXInput(*this), _joypadDirectInput(*this) { initialize(); }
~InputWindows() { terminate(); }
LPDIRECTINPUT8 directinputContext = nullptr;
auto ready() -> bool { return _ready; }
struct Settings {
uintptr_t handle = 0;
} settings;
auto context() -> uintptr { return _context; }
auto cap(const string& name) -> bool {
if(name == Input::Handle) return true;
if(name == Input::KeyboardSupport) return true;
if(name == Input::MouseSupport) return true;
if(name == Input::JoypadSupport) return true;
if(name == Input::JoypadRumbleSupport) return true;
return false;
}
auto get(const string& name) -> any {
if(name == Input::Handle) return (uintptr_t)settings.handle;
return {};
}
auto set(const string& name, const any& value) -> bool {
if(name == Input::Handle && value.is<uintptr_t>()) {
settings.handle = value.get<uintptr_t>();
return true;
}
return false;
}
auto acquire() -> bool {
return rawinputMouse.acquire();
}
auto release() -> bool {
return rawinputMouse.release();
auto setContext(uintptr context) -> bool {
if(_context == context) return true;
_context = context;
return initialize();
}
auto acquired() -> bool {
return rawinputMouse.acquired();
return _mouse.acquired();
}
auto acquire() -> bool {
return _mouse.acquire();
}
auto release() -> bool {
return _mouse.release();
}
auto poll() -> vector<shared_pointer<HID::Device>> {
vector<shared_pointer<HID::Device>> devices;
rawinputKeyboard.poll(devices);
rawinputMouse.poll(devices);
xinput.poll(devices);
directinput.poll(devices);
_keyboard.poll(devices);
_mouse.poll(devices);
_joypadXInput.poll(devices);
_joypadDirectInput.poll(devices);
return devices;
}
auto rumble(uint64_t id, bool enable) -> bool {
if(xinput.rumble(id, enable)) return true;
if(directinput.rumble(id, enable)) return true;
if(_joypadXInput.rumble(id, enable)) return true;
if(_joypadDirectInput.rumble(id, enable)) return true;
return false;
}
auto init() -> bool {
if(rawinput.initialized == false) {
private:
auto initialize() -> bool {
terminate();
if(!_context) return false;
if(!rawinput.initialized) {
rawinput.initialized = true;
rawinput.mutex = CreateMutex(NULL, FALSE, NULL);
CreateThread(NULL, 0, RawInputThreadProc, 0, 0, NULL);
rawinput.mutex = CreateMutex(nullptr, false, nullptr);
CreateThread(nullptr, 0, RawInputThreadProc, 0, 0, nullptr);
do {
Sleep(1);
WaitForSingleObject(rawinput.mutex, INFINITE);
ReleaseMutex(rawinput.mutex);
} while(rawinput.ready == false);
} while(!rawinput.ready);
}
DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&directinputContext, 0);
if(directinputContext == nullptr) return false;
DirectInput8Create(GetModuleHandle(0), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_directInputContext, 0);
if(!_directInputContext) return false;
if(rawinputKeyboard.init() == false) return false;
if(rawinputMouse.init(settings.handle) == false) return false;
bool xinputAvailable = xinput.init();
if(directinput.init(settings.handle, directinputContext, xinputAvailable) == false) return false;
return true;
if(!_keyboard.initialize()) return false;
if(!_mouse.initialize(_context)) return false;
bool xinputAvailable = _joypadXInput.initialize();
if(!_joypadDirectInput.initialize(_context, _directInputContext, xinputAvailable)) return false;
return _ready = true;
}
auto term() -> void {
rawinputKeyboard.term();
rawinputMouse.term();
xinput.term();
directinput.term();
auto terminate() -> void {
_ready = false;
if(directinputContext) { directinputContext->Release(); directinputContext = nullptr; }
_keyboard.terminate();
_mouse.terminate();
_joypadXInput.terminate();
_joypadDirectInput.terminate();
if(_directInputContext) {
_directInputContext->Release();
_directInputContext = nullptr;
}
}
bool _ready = false;
uintptr _context = 0;
InputKeyboardRawInput _keyboard;
InputMouseRawInput _mouse;
InputJoypadXInput _joypadXInput;
InputJoypadDirectInput _joypadDirectInput;
LPDIRECTINPUT8 _directInputContext = nullptr;
};

View File

@@ -8,51 +8,25 @@
#include "mouse/xlib.cpp"
struct InputXlib : Input {
InputKeyboardXlib xlibKeyboard;
InputMouseXlib xlibMouse;
InputXlib() : xlibKeyboard(*this), xlibMouse(*this) {}
~InputXlib() { term(); }
InputXlib() : _keyboard(*this), _mouse(*this) { initialize(); }
~InputXlib() { terminate(); }
struct Settings {
uintptr_t handle = 0;
} settings;
auto cap(const string& name) -> bool {
if(name == Input::KeyboardSupport) return true;
if(name == Input::MouseSupport) return true;
return false;
}
auto get(const string& name) -> any {
if(name == Input::Handle) return (uintptr_t)settings.handle;
return {};
}
auto set(const string& name, const any& value) -> bool {
if(name == Input::Handle && value.is<uintptr_t>()) {
settings.handle = value.get<uintptr_t>();
return true;
}
return false;
auto acquired() -> bool {
return _mouse.acquired();
}
auto acquire() -> bool {
return xlibMouse.acquire();
return _mouse.acquire();
}
auto release() -> bool {
return xlibMouse.release();
}
auto acquired() -> bool {
return xlibMouse.acquired();
return _mouse.release();
}
auto poll() -> vector<shared_pointer<HID::Device>> {
vector<shared_pointer<HID::Device>> devices;
xlibKeyboard.poll(devices);
xlibMouse.poll(devices);
_keyboard.poll(devices);
_mouse.poll(devices);
return devices;
}
@@ -60,14 +34,23 @@ struct InputXlib : Input {
return false;
}
auto init() -> bool {
if(!xlibKeyboard.init()) return false;
if(!xlibMouse.init(settings.handle)) return false;
return true;
private:
auto initialize() -> bool {
terminate();
if(!_keyboard.initialize()) return false;
if(!_mouse.initialize(_context)) return false;
return _ready = true;
}
auto term() -> void {
xlibKeyboard.term();
xlibMouse.term();
auto terminate() -> void {
_ready = false;
_keyboard.terminate();
_mouse.terminate();
}
bool _ready = false;
uintptr _context = 0;
InputKeyboardXlib _keyboard;
InputMouseXlib _mouse;
};