mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-21 14:31:26 +02:00
Update to v094r24 release.
byuu says: Finally!! Compilation works once again on Windows. However, it's pretty buggy. Modality isn't really working right, you can still poke at other windows, but when you select ListView items, they redraw as empty boxes (need to process WM_DRAWITEM before checking modality.) The program crashes when you close it (probably a ruby driver's term() function, that's what it usually is.) The Layout::setEnabled(false) call isn't working right, so you get that annoying chiming sound and cursor movement when mapping keyboard keys to game inputs. The column sizing seems off a bit on first display for the Hotkeys tab. And probably lots more.
This commit is contained in:
@@ -1,39 +1,42 @@
|
||||
/*
|
||||
audio.directsound (2007-12-26)
|
||||
author: byuu
|
||||
*/
|
||||
|
||||
#include <dsound.h>
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pAudioDS {
|
||||
public:
|
||||
LPDIRECTSOUND ds;
|
||||
LPDIRECTSOUNDBUFFER dsb_p, dsb_b;
|
||||
struct pAudioDS {
|
||||
LPDIRECTSOUND ds = nullptr;
|
||||
LPDIRECTSOUNDBUFFER dsb_p = nullptr;
|
||||
LPDIRECTSOUNDBUFFER dsb_b = nullptr;
|
||||
DSBUFFERDESC dsbd;
|
||||
WAVEFORMATEX wfx;
|
||||
|
||||
struct {
|
||||
unsigned rings;
|
||||
unsigned latency;
|
||||
unsigned rings = 0;
|
||||
unsigned latency = 0;
|
||||
|
||||
uint32_t* buffer;
|
||||
unsigned bufferoffset;
|
||||
uint32_t* buffer = nullptr;
|
||||
unsigned bufferoffset = 0;
|
||||
|
||||
unsigned readring;
|
||||
unsigned writering;
|
||||
int distance;
|
||||
unsigned readring = 0;
|
||||
unsigned writering = 0;
|
||||
int distance = 0;
|
||||
} device;
|
||||
|
||||
struct {
|
||||
HWND handle;
|
||||
bool synchronize;
|
||||
unsigned frequency;
|
||||
unsigned latency;
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = false;
|
||||
unsigned frequency = 22050;
|
||||
unsigned latency = 120;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
pAudioDS() {
|
||||
settings.handle = GetDesktopWindow();
|
||||
}
|
||||
|
||||
~pAudioDS() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Audio::Handle) return true;
|
||||
if(name == Audio::Synchronize) return true;
|
||||
if(name == Audio::Frequency) return true;
|
||||
@@ -41,34 +44,34 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Audio::Handle) return (uintptr_t)settings.handle;
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Audio::Handle && value.is<uintptr_t>()) {
|
||||
settings.handle = (HWND)value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(name == Audio::Synchronize && value.is<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
if(ds) clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(name == Audio::Frequency && value.is<unsigned>()) {
|
||||
settings.frequency = value.get<unsigned>();
|
||||
if(ds) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Latency) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
if(name == Audio::Latency && value.is<unsigned>()) {
|
||||
settings.latency = value.get<unsigned>();
|
||||
if(ds) init();
|
||||
return true;
|
||||
}
|
||||
@@ -76,7 +79,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void sample(uint16_t left, uint16_t right) {
|
||||
auto sample(uint16_t left, uint16_t right) -> void {
|
||||
device.buffer[device.bufferoffset++] = left + (right << 16);
|
||||
if(device.bufferoffset < device.latency) return;
|
||||
device.bufferoffset = 0;
|
||||
@@ -113,7 +116,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
device.readring = 0;
|
||||
device.writering = device.rings - 1;
|
||||
device.distance = device.rings - 1;
|
||||
@@ -134,7 +137,7 @@ public:
|
||||
dsb_b->Play(0, 0, DSBPLAY_LOOPING);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
device.rings = 8;
|
||||
@@ -175,7 +178,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
if(device.buffer) {
|
||||
delete[] device.buffer;
|
||||
device.buffer = 0;
|
||||
@@ -185,23 +188,6 @@ public:
|
||||
if(dsb_p) { dsb_p->Stop(); dsb_p->Release(); dsb_p = 0; }
|
||||
if(ds) { ds->Release(); ds = 0; }
|
||||
}
|
||||
|
||||
pAudioDS() {
|
||||
ds = 0;
|
||||
dsb_p = 0;
|
||||
dsb_b = 0;
|
||||
|
||||
device.buffer = 0;
|
||||
device.bufferoffset = 0;
|
||||
device.readring = 0;
|
||||
device.writering = 0;
|
||||
device.distance = 0;
|
||||
|
||||
settings.handle = GetDesktopWindow();
|
||||
settings.synchronize = false;
|
||||
settings.frequency = 22050;
|
||||
settings.latency = 120;
|
||||
}
|
||||
};
|
||||
|
||||
DeclareAudio(DS)
|
||||
|
@@ -3,11 +3,10 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pAudioXAudio2: public IXAudio2VoiceCallback {
|
||||
public:
|
||||
IXAudio2* pXAudio2;
|
||||
IXAudio2MasteringVoice* pMasterVoice;
|
||||
IXAudio2SourceVoice* pSourceVoice;
|
||||
struct pAudioXAudio2 : public IXAudio2VoiceCallback {
|
||||
IXAudio2* pXAudio2 = nullptr;
|
||||
IXAudio2MasteringVoice* pMasterVoice = nullptr;
|
||||
IXAudio2SourceVoice* pSourceVoice = nullptr;
|
||||
|
||||
//inherited from IXAudio2VoiceCallback
|
||||
STDMETHODIMP_(void) OnBufferStart(void* pBufferContext){}
|
||||
@@ -18,51 +17,55 @@ public:
|
||||
STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
|
||||
|
||||
struct {
|
||||
unsigned buffers;
|
||||
unsigned latency;
|
||||
unsigned buffers = 0;
|
||||
unsigned latency = 0;
|
||||
|
||||
uint32_t* buffer;
|
||||
unsigned bufferoffset;
|
||||
uint32_t* buffer = nullptr;
|
||||
unsigned bufferoffset = 0;
|
||||
|
||||
volatile long submitbuffers;
|
||||
unsigned writebuffer;
|
||||
volatile long submitbuffers = 0;
|
||||
unsigned writebuffer = 0;
|
||||
} device;
|
||||
|
||||
struct {
|
||||
bool synchronize;
|
||||
unsigned frequency;
|
||||
unsigned latency;
|
||||
bool synchronize = false;
|
||||
unsigned frequency = 22050;
|
||||
unsigned latency = 120;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pAudioXAudio2() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
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) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Audio::Synchronize) return settings.synchronize;
|
||||
if(name == Audio::Frequency) return settings.frequency;
|
||||
if(name == Audio::Latency) return settings.latency;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Audio::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Audio::Synchronize && value.is<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
if(pXAudio2) clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Frequency) {
|
||||
settings.frequency = any_cast<unsigned>(value);
|
||||
if(name == Audio::Frequency && value.is<unsigned>()) {
|
||||
settings.frequency = value.get<unsigned>();
|
||||
if(pXAudio2) init();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Audio::Latency) {
|
||||
settings.latency = any_cast<unsigned>(value);
|
||||
if(name == Audio::Latency && value.is<unsigned>()) {
|
||||
settings.latency = value.get<unsigned>();
|
||||
if(pXAudio2) init();
|
||||
return true;
|
||||
}
|
||||
@@ -70,7 +73,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void pushbuffer(unsigned bytes, uint32_t* pAudioData) {
|
||||
auto pushbuffer(unsigned bytes, uint32_t* pAudioData) -> void {
|
||||
XAUDIO2_BUFFER xa2buffer = {0};
|
||||
xa2buffer.AudioBytes = bytes;
|
||||
xa2buffer.pAudioData = reinterpret_cast<BYTE*>(pAudioData);
|
||||
@@ -79,7 +82,7 @@ public:
|
||||
pSourceVoice->SubmitSourceBuffer(&xa2buffer);
|
||||
}
|
||||
|
||||
void sample(uint16_t left, uint16_t right) {
|
||||
auto sample(uint16_t left, uint16_t right) -> void {
|
||||
device.buffer[device.writebuffer * device.latency + device.bufferoffset++] = left + (right << 16);
|
||||
if(device.bufferoffset < device.latency) return;
|
||||
device.bufferoffset = 0;
|
||||
@@ -100,7 +103,7 @@ public:
|
||||
device.writebuffer = (device.writebuffer + 1) % device.buffers;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
if(!pSourceVoice) return;
|
||||
pSourceVoice->Stop(0);
|
||||
pSourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers
|
||||
@@ -113,7 +116,7 @@ public:
|
||||
pSourceVoice->Start(0);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
device.buffers = 8;
|
||||
@@ -160,7 +163,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
if(pSourceVoice) {
|
||||
pSourceVoice->Stop(0);
|
||||
pSourceVoice->DestroyVoice();
|
||||
@@ -183,21 +186,6 @@ public:
|
||||
STDMETHODIMP_(void) OnBufferEnd(void* pBufferContext) {
|
||||
InterlockedDecrement(&device.submitbuffers);
|
||||
}
|
||||
|
||||
pAudioXAudio2() {
|
||||
pXAudio2 = nullptr;
|
||||
pMasterVoice = nullptr;
|
||||
pSourceVoice = nullptr;
|
||||
|
||||
device.buffer = nullptr;
|
||||
device.bufferoffset = 0;
|
||||
device.submitbuffers = 0;
|
||||
device.writebuffer = 0;
|
||||
|
||||
settings.synchronize = false;
|
||||
settings.frequency = 22050;
|
||||
settings.latency = 120;
|
||||
}
|
||||
};
|
||||
|
||||
DeclareAudio(XAudio2)
|
||||
|
@@ -3,13 +3,13 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
BOOL CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p);
|
||||
BOOL CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p);
|
||||
BOOL CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p);
|
||||
auto CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p) -> BOOL;
|
||||
auto CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL;
|
||||
auto CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL;
|
||||
|
||||
struct InputJoypadDirectInput {
|
||||
struct Joypad {
|
||||
HID::Joypad hid;
|
||||
shared_pointer<HID::Joypad> hid{new HID::Joypad};
|
||||
|
||||
LPDIRECTINPUTDEVICE8 device = nullptr;
|
||||
LPDIRECTINPUTEFFECT effect = nullptr;
|
||||
@@ -27,14 +27,14 @@ struct InputJoypadDirectInput {
|
||||
bool xinputAvailable = false;
|
||||
unsigned effects = 0;
|
||||
|
||||
void assign(HID::Joypad& hid, unsigned groupID, unsigned inputID, int16_t value) {
|
||||
auto& group = hid.group[groupID];
|
||||
if(group.input[inputID].value == value) return;
|
||||
if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value);
|
||||
group.input[inputID].value = value;
|
||||
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
|
||||
auto& group = hid->group(groupID);
|
||||
if(group.input(inputID).value() == value) return;
|
||||
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
|
||||
group.input(inputID).setValue(value);
|
||||
}
|
||||
|
||||
void poll(vector<HID::Device*>& devices) {
|
||||
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
|
||||
for(auto& jp : joypads) {
|
||||
if(FAILED(jp.device->Poll())) jp.device->Acquire();
|
||||
|
||||
@@ -68,13 +68,13 @@ struct InputJoypadDirectInput {
|
||||
assign(jp.hid, HID::Joypad::GroupID::Button, n, (bool)state.rgbButtons[n]);
|
||||
}
|
||||
|
||||
devices.append(&jp.hid);
|
||||
devices.append(jp.hid);
|
||||
}
|
||||
}
|
||||
|
||||
bool rumble(uint64_t id, bool enable) {
|
||||
auto rumble(uint64_t id, bool enable) -> bool {
|
||||
for(auto& jp : joypads) {
|
||||
if(jp.hid.id != id) continue;
|
||||
if(jp.hid->id() != id) continue;
|
||||
if(jp.effect == nullptr) continue;
|
||||
|
||||
if(enable) jp.effect->Start(1, 0);
|
||||
@@ -85,7 +85,7 @@ struct InputJoypadDirectInput {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init(uintptr_t handle, LPDIRECTINPUT8 context, bool xinputAvailable) {
|
||||
auto init(uintptr_t handle, LPDIRECTINPUT8 context, bool xinputAvailable) -> bool {
|
||||
this->handle = handle;
|
||||
this->context = context;
|
||||
this->xinputAvailable = xinputAvailable;
|
||||
@@ -93,7 +93,7 @@ struct InputJoypadDirectInput {
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
for(auto& jp : joypads) {
|
||||
jp.device->Unacquire();
|
||||
if(jp.effect) jp.effect->Release();
|
||||
@@ -103,7 +103,7 @@ struct InputJoypadDirectInput {
|
||||
context = nullptr;
|
||||
}
|
||||
|
||||
bool initJoypad(const DIDEVICEINSTANCE* instance) {
|
||||
auto initJoypad(const DIDEVICEINSTANCE* instance) -> bool {
|
||||
Joypad jp;
|
||||
jp.vendorID = instance->guidProduct.Data1 >> 0;
|
||||
jp.productID = instance->guidProduct.Data1 >> 16;
|
||||
@@ -127,7 +127,7 @@ struct InputJoypadDirectInput {
|
||||
effects = 0;
|
||||
device->EnumObjects(DirectInput_EnumJoypadAxesCallback, (void*)this, DIDFT_ABSAXIS);
|
||||
device->EnumObjects(DirectInput_EnumJoypadEffectsCallback, (void*)this, DIDFT_FFACTUATOR);
|
||||
jp.hid.rumble = effects > 0;
|
||||
jp.hid->setRumble(effects > 0);
|
||||
|
||||
DIPROPGUIDANDPATH property;
|
||||
memset(&property, 0, sizeof(DIPROPGUIDANDPATH));
|
||||
@@ -138,9 +138,9 @@ struct InputJoypadDirectInput {
|
||||
device->GetProperty(DIPROP_GUIDANDPATH, &property.diph);
|
||||
string devicePath = (const char*)utf8_t(property.wszPath);
|
||||
jp.pathID = Hash::CRC32(devicePath.data(), devicePath.size()).value();
|
||||
jp.hid.id = (uint64_t)jp.pathID << 32 | jp.vendorID << 16 | jp.productID << 0;
|
||||
jp.hid->setID((uint64_t)jp.pathID << 32 | jp.vendorID << 16 | jp.productID << 0);
|
||||
|
||||
if(jp.hid.rumble) {
|
||||
if(jp.hid->rumble()) {
|
||||
//disable auto-centering spring for rumble support
|
||||
DIPROPDWORD property;
|
||||
memset(&property, 0, sizeof(DIPROPDWORD));
|
||||
@@ -174,15 +174,15 @@ struct InputJoypadDirectInput {
|
||||
device->CreateEffect(GUID_ConstantForce, &effect, &jp.effect, NULL);
|
||||
}
|
||||
|
||||
for(unsigned n = 0; n < 6; n++) jp.hid.axis().append({n});
|
||||
for(unsigned n = 0; n < 8; n++) jp.hid.hat().append({n});
|
||||
for(unsigned n = 0; n < 128; n++) jp.hid.button().append({n});
|
||||
for(unsigned n = 0; n < 6; n++) jp.hid->axes().append(n);
|
||||
for(unsigned n = 0; n < 8; n++) jp.hid->hats().append(n);
|
||||
for(unsigned n = 0; n < 128; n++) jp.hid->buttons().append(n);
|
||||
joypads.append(jp);
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
bool initAxis(const DIDEVICEOBJECTINSTANCE* instance) {
|
||||
auto initAxis(const DIDEVICEOBJECTINSTANCE* instance) -> bool {
|
||||
DIPROPRANGE range;
|
||||
memset(&range, 0, sizeof(DIPROPRANGE));
|
||||
range.diph.dwSize = sizeof(DIPROPRANGE);
|
||||
@@ -195,21 +195,21 @@ struct InputJoypadDirectInput {
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
bool initEffect(const DIDEVICEOBJECTINSTANCE* instance) {
|
||||
auto initEffect(const DIDEVICEOBJECTINSTANCE* instance) -> bool {
|
||||
effects++;
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
};
|
||||
|
||||
BOOL CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p) {
|
||||
auto CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p) -> BOOL {
|
||||
return ((InputJoypadDirectInput*)p)->initJoypad(instance);
|
||||
}
|
||||
|
||||
BOOL CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) {
|
||||
auto CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL {
|
||||
return ((InputJoypadDirectInput*)p)->initAxis(instance);
|
||||
}
|
||||
|
||||
BOOL CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) {
|
||||
auto CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL {
|
||||
return ((InputJoypadDirectInput*)p)->initEffect(instance);
|
||||
}
|
||||
|
||||
|
@@ -27,19 +27,19 @@ struct InputJoypadXInput {
|
||||
pXInputSetState XInputSetState = nullptr;
|
||||
|
||||
struct Joypad {
|
||||
HID::Joypad hid;
|
||||
unsigned id;
|
||||
shared_pointer<HID::Joypad> hid{new HID::Joypad};
|
||||
unsigned id = 0;
|
||||
};
|
||||
vector<Joypad> joypads;
|
||||
|
||||
void assign(HID::Joypad& hid, unsigned groupID, unsigned inputID, int16_t value) {
|
||||
auto& group = hid.group[groupID];
|
||||
if(group.input[inputID].value == value) return;
|
||||
if(input.onChange) input.onChange(hid, groupID, inputID, group.input[inputID].value, value);
|
||||
group.input[inputID].value = value;
|
||||
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
|
||||
auto& group = hid->group(groupID);
|
||||
if(group.input(inputID).value() == value) return;
|
||||
if(input.onChange) input.onChange(hid, groupID, inputID, group.input(inputID).value(), value);
|
||||
group.input(inputID).setValue(value);
|
||||
}
|
||||
|
||||
void poll(vector<HID::Device*>& devices) {
|
||||
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
|
||||
for(auto& jp : joypads) {
|
||||
XINPUT_STATE state;
|
||||
if(XInputGetStateEx(jp.id, &state) != ERROR_SUCCESS) continue;
|
||||
@@ -83,13 +83,13 @@ struct InputJoypadXInput {
|
||||
assign(jp.hid, HID::Joypad::GroupID::Button, 9, (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB));
|
||||
assign(jp.hid, HID::Joypad::GroupID::Button, 10, (bool)(state.Gamepad.wButtons & XINPUT_GAMEPAD_GUIDE));
|
||||
|
||||
devices.append(&jp.hid);
|
||||
devices.append(jp.hid);
|
||||
}
|
||||
}
|
||||
|
||||
bool rumble(uint64_t id, bool enable) {
|
||||
auto rumble(uint64_t id, bool enable) -> bool {
|
||||
for(auto& jp : joypads) {
|
||||
if(jp.hid.id != id) continue;
|
||||
if(jp.hid->id() != id) continue;
|
||||
|
||||
XINPUT_VIBRATION vibration;
|
||||
memset(&vibration, 0, sizeof(XINPUT_VIBRATION));
|
||||
@@ -102,7 +102,7 @@ struct InputJoypadXInput {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
if(!libxinput) libxinput = LoadLibraryA("xinput1_3.dll");
|
||||
if(!libxinput) return false;
|
||||
|
||||
@@ -118,30 +118,31 @@ struct InputJoypadXInput {
|
||||
for(unsigned id = 0; id < 4; id++) {
|
||||
Joypad jp;
|
||||
jp.id = id;
|
||||
jp.hid.id = (uint64_t)(1 + id) << 32 | 0x045e << 16 | 0x028e << 0; //Xbox 360 Player# + VendorID + ProductID
|
||||
jp.hid->setID((uint64_t)(1 + id) << 32 | 0x045e << 16 | 0x028e << 0); //Xbox 360 Player# + VendorID + ProductID
|
||||
jp.hid->setRumble(true);
|
||||
|
||||
jp.hid.axis().append({"LeftThumbX"});
|
||||
jp.hid.axis().append({"LeftThumbY"});
|
||||
jp.hid.axis().append({"RightThumbX"});
|
||||
jp.hid.axis().append({"RightThumbY"});
|
||||
jp.hid->axes().append("LeftThumbX");
|
||||
jp.hid->axes().append("LeftThumbY");
|
||||
jp.hid->axes().append("RightThumbX");
|
||||
jp.hid->axes().append("RightThumbY");
|
||||
|
||||
jp.hid.hat().append({"HatX"});
|
||||
jp.hid.hat().append({"HatY"});
|
||||
jp.hid->hats().append("HatX");
|
||||
jp.hid->hats().append("HatY");
|
||||
|
||||
jp.hid.trigger().append({"LeftTrigger"});
|
||||
jp.hid.trigger().append({"RightTrigger"});
|
||||
jp.hid->triggers().append("LeftTrigger");
|
||||
jp.hid->triggers().append("RightTrigger");
|
||||
|
||||
jp.hid.button().append({"A"});
|
||||
jp.hid.button().append({"B"});
|
||||
jp.hid.button().append({"X"});
|
||||
jp.hid.button().append({"Y"});
|
||||
jp.hid.button().append({"Back"});
|
||||
jp.hid.button().append({"Start"});
|
||||
jp.hid.button().append({"LeftShoulder"});
|
||||
jp.hid.button().append({"RightShoulder"});
|
||||
jp.hid.button().append({"LeftThumb"});
|
||||
jp.hid.button().append({"RightThumb"});
|
||||
jp.hid.button().append({"Guide"});
|
||||
jp.hid->buttons().append("A");
|
||||
jp.hid->buttons().append("B");
|
||||
jp.hid->buttons().append("X");
|
||||
jp.hid->buttons().append("Y");
|
||||
jp.hid->buttons().append("Back");
|
||||
jp.hid->buttons().append("Start");
|
||||
jp.hid->buttons().append("LeftShoulder");
|
||||
jp.hid->buttons().append("RightShoulder");
|
||||
jp.hid->buttons().append("LeftThumb");
|
||||
jp.hid->buttons().append("RightThumb");
|
||||
jp.hid->buttons().append("Guide");
|
||||
|
||||
joypads.append(jp);
|
||||
}
|
||||
@@ -149,7 +150,7 @@ struct InputJoypadXInput {
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
if(!libxinput) return;
|
||||
|
||||
FreeLibrary(libxinput);
|
||||
|
@@ -13,10 +13,10 @@ struct InputKeyboardRawInput {
|
||||
vector<Key> keys;
|
||||
|
||||
struct Keyboard {
|
||||
HID::Keyboard hid;
|
||||
shared_pointer<HID::Keyboard> hid{new HID::Keyboard};
|
||||
} kb;
|
||||
|
||||
void update(RAWINPUT* input) {
|
||||
auto update(RAWINPUT* input) -> void {
|
||||
unsigned code = input->data.keyboard.MakeCode;
|
||||
unsigned flag = input->data.keyboard.Flags;
|
||||
|
||||
@@ -26,19 +26,19 @@ struct InputKeyboardRawInput {
|
||||
}
|
||||
}
|
||||
|
||||
void assign(unsigned inputID, bool value) {
|
||||
auto& group = kb.hid.group[HID::Keyboard::GroupID::Button];
|
||||
if(group.input[inputID].value == value) return;
|
||||
if(input.onChange) input.onChange(kb.hid, HID::Keyboard::GroupID::Button, inputID, group.input[inputID].value, value);
|
||||
group.input[inputID].value = value;
|
||||
auto assign(unsigned inputID, bool value) -> void {
|
||||
auto& group = kb.hid->buttons();
|
||||
if(group.input(inputID).value() == value) return;
|
||||
if(input.onChange) input.onChange(kb.hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
|
||||
group.input(inputID).setValue(value);
|
||||
}
|
||||
|
||||
void poll(vector<HID::Device*>& devices) {
|
||||
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
|
||||
for(unsigned n = 0; n < keys.size(); n++) assign(n, keys[n].value);
|
||||
devices.append(&kb.hid);
|
||||
devices.append(kb.hid);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
rawinput.updateKeyboard = {&InputKeyboardRawInput::update, this};
|
||||
|
||||
//Pause sends 0x001d,4 + 0x0045,0; NumLock sends only 0x0045,0
|
||||
@@ -163,8 +163,8 @@ struct InputKeyboardRawInput {
|
||||
keys.append({0x005c, 2, "RightSuper"});
|
||||
keys.append({0x005d, 2, "Menu"});
|
||||
|
||||
kb.hid.id = 1;
|
||||
for(auto& key : keys) kb.hid.button().append({key.name});
|
||||
kb.hid->setID(1);
|
||||
for(auto& key : keys) kb.hid->buttons().append(key.name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ struct InputMouseRawInput {
|
||||
bool mouseAcquired = false;
|
||||
|
||||
struct Mouse {
|
||||
HID::Mouse hid;
|
||||
shared_pointer<HID::Mouse> hid{new HID::Mouse};
|
||||
|
||||
signed relativeX = 0;
|
||||
signed relativeY = 0;
|
||||
@@ -16,7 +16,7 @@ struct InputMouseRawInput {
|
||||
bool buttons[5] = {0};
|
||||
} ms;
|
||||
|
||||
bool acquire() {
|
||||
auto acquire() -> bool {
|
||||
if(mouseAcquired == false) {
|
||||
mouseAcquired = true;
|
||||
ShowCursor(false);
|
||||
@@ -24,17 +24,17 @@ struct InputMouseRawInput {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool unacquire() {
|
||||
auto unacquire() -> bool {
|
||||
if(mouseAcquired == true) {
|
||||
mouseAcquired = false;
|
||||
ReleaseCapture();
|
||||
ClipCursor(NULL);
|
||||
ClipCursor(nullptr);
|
||||
ShowCursor(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acquired() {
|
||||
auto acquired() -> bool {
|
||||
if(mouseAcquired == true) {
|
||||
SetFocus((HWND)handle);
|
||||
SetCapture((HWND)handle);
|
||||
@@ -45,7 +45,7 @@ struct InputMouseRawInput {
|
||||
return GetCapture() == (HWND)handle;
|
||||
}
|
||||
|
||||
void update(RAWINPUT* input) {
|
||||
auto update(RAWINPUT* input) -> void {
|
||||
if((input->data.mouse.usFlags & 1) == MOUSE_MOVE_RELATIVE) {
|
||||
ms.relativeX += input->data.mouse.lLastX;
|
||||
ms.relativeY += input->data.mouse.lLastY;
|
||||
@@ -67,14 +67,14 @@ struct InputMouseRawInput {
|
||||
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP ) ms.buttons[4] = 0;
|
||||
}
|
||||
|
||||
void assign(unsigned groupID, unsigned inputID, int16_t value) {
|
||||
auto& group = ms.hid.group[groupID];
|
||||
if(group.input[inputID].value == value) return;
|
||||
if(input.onChange) input.onChange(ms.hid, groupID, inputID, group.input[inputID].value, value);
|
||||
group.input[inputID].value = value;
|
||||
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
|
||||
auto& group = ms.hid->group(groupID);
|
||||
if(group.input(inputID).value() == value) return;
|
||||
if(input.onChange) input.onChange(ms.hid, groupID, inputID, group.input(inputID).value(), value);
|
||||
group.input(inputID).setValue(value);
|
||||
}
|
||||
|
||||
void poll(vector<HID::Device*>& devices) {
|
||||
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
|
||||
assign(HID::Mouse::GroupID::Axis, 0, ms.relativeX);
|
||||
assign(HID::Mouse::GroupID::Axis, 1, ms.relativeY);
|
||||
assign(HID::Mouse::GroupID::Axis, 2, ms.relativeZ);
|
||||
@@ -91,29 +91,29 @@ struct InputMouseRawInput {
|
||||
ms.relativeY = 0;
|
||||
ms.relativeZ = 0;
|
||||
|
||||
devices.append(&ms.hid);
|
||||
devices.append(ms.hid);
|
||||
}
|
||||
|
||||
bool init(uintptr_t handle) {
|
||||
auto init(uintptr_t handle) -> bool {
|
||||
this->handle = handle;
|
||||
|
||||
ms.hid.id = 2;
|
||||
ms.hid->setID(2);
|
||||
|
||||
ms.hid.axis().append({"X"});
|
||||
ms.hid.axis().append({"Y"});
|
||||
ms.hid.axis().append({"Z"});
|
||||
ms.hid->axes().append("X");
|
||||
ms.hid->axes().append("Y");
|
||||
ms.hid->axes().append("Z");
|
||||
|
||||
ms.hid.button().append({"Left"});
|
||||
ms.hid.button().append({"Middle"});
|
||||
ms.hid.button().append({"Right"});
|
||||
ms.hid.button().append({"Up"});
|
||||
ms.hid.button().append({"Down"});
|
||||
ms.hid->buttons().append("Left");
|
||||
ms.hid->buttons().append("Middle");
|
||||
ms.hid->buttons().append("Right");
|
||||
ms.hid->buttons().append("Up");
|
||||
ms.hid->buttons().append("Down");
|
||||
|
||||
rawinput.updateMouse = {&InputMouseRawInput::update, this};
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
unacquire();
|
||||
}
|
||||
};
|
||||
|
@@ -3,18 +3,18 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
LRESULT CALLBACK RawInputWindowProc(HWND, UINT, WPARAM, LPARAM);
|
||||
auto CALLBACK RawInputWindowProc(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
|
||||
|
||||
struct RawInput {
|
||||
HANDLE mutex;
|
||||
HWND hwnd;
|
||||
HANDLE mutex = nullptr;
|
||||
HWND hwnd = nullptr;
|
||||
bool ready = false;
|
||||
bool initialized = false;
|
||||
function<void (RAWINPUT*)> updateKeyboard;
|
||||
function<void (RAWINPUT*)> updateMouse;
|
||||
|
||||
struct Device {
|
||||
HANDLE handle;
|
||||
HANDLE handle = nullptr;
|
||||
string path;
|
||||
enum class Type : unsigned { Keyboard, Mouse, Joypad } type;
|
||||
uint16_t vendorID = 0;
|
||||
@@ -23,14 +23,14 @@ struct RawInput {
|
||||
};
|
||||
vector<Device> devices;
|
||||
|
||||
maybe<Device&> find(uint16_t vendorID, uint16_t productID) {
|
||||
auto find(uint16_t vendorID, uint16_t productID) -> maybe<Device&> {
|
||||
for(auto& device : devices) {
|
||||
if(device.vendorID == vendorID && device.productID == productID) return device;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
void scanDevices() {
|
||||
auto scanDevices() -> void {
|
||||
devices.reset();
|
||||
|
||||
unsigned deviceCount = 0;
|
||||
@@ -79,7 +79,7 @@ struct RawInput {
|
||||
delete[] list;
|
||||
}
|
||||
|
||||
LRESULT windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
auto windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
if(msg != WM_INPUT) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
|
||||
unsigned size = 0;
|
||||
@@ -102,7 +102,7 @@ struct RawInput {
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
auto main() -> void {
|
||||
WNDCLASS wc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
@@ -148,12 +148,12 @@ struct RawInput {
|
||||
|
||||
static RawInput rawinput;
|
||||
|
||||
DWORD WINAPI RawInputThreadProc(void*) {
|
||||
auto WINAPI RawInputThreadProc(void*) -> DWORD {
|
||||
rawinput.main();
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK RawInputWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||
auto CALLBACK RawInputWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
|
||||
return rawinput.windowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
|
@@ -22,7 +22,11 @@ struct pInputWindows {
|
||||
uintptr_t handle = 0;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pInputWindows() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Input::Handle) return true;
|
||||
if(name == Input::KeyboardSupport) return true;
|
||||
if(name == Input::MouseSupport) return true;
|
||||
@@ -31,33 +35,33 @@ struct pInputWindows {
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Input::Handle) return (uintptr_t)settings.handle;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Input::Handle) {
|
||||
settings.handle = any_cast<uintptr_t>(value);
|
||||
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;
|
||||
}
|
||||
|
||||
bool acquire() {
|
||||
auto acquire() -> bool {
|
||||
return rawinputMouse.acquire();
|
||||
}
|
||||
|
||||
bool unacquire() {
|
||||
auto unacquire() -> bool {
|
||||
return rawinputMouse.unacquire();
|
||||
}
|
||||
|
||||
bool acquired() {
|
||||
auto acquired() -> bool {
|
||||
return rawinputMouse.acquired();
|
||||
}
|
||||
|
||||
vector<HID::Device*> poll() {
|
||||
vector<HID::Device*> devices;
|
||||
auto poll() -> vector<shared_pointer<HID::Device>> {
|
||||
vector<shared_pointer<HID::Device>> devices;
|
||||
rawinputKeyboard.poll(devices);
|
||||
rawinputMouse.poll(devices);
|
||||
xinput.poll(devices);
|
||||
@@ -65,13 +69,13 @@ struct pInputWindows {
|
||||
return devices;
|
||||
}
|
||||
|
||||
bool rumble(uint64_t id, bool enable) {
|
||||
auto rumble(uint64_t id, bool enable) -> bool {
|
||||
if(xinput.rumble(id, enable)) return true;
|
||||
if(directinput.rumble(id, enable)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
if(rawinput.initialized == false) {
|
||||
rawinput.initialized = true;
|
||||
rawinput.mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
@@ -94,7 +98,7 @@ struct pInputWindows {
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
rawinputKeyboard.term();
|
||||
rawinputMouse.term();
|
||||
xinput.term();
|
||||
|
@@ -11,24 +11,24 @@ typedef HRESULT (__stdcall* TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DT
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pVideoD3D {
|
||||
public:
|
||||
LPDIRECT3D9 lpd3d;
|
||||
LPDIRECT3DDEVICE9 device;
|
||||
LPDIRECT3DVERTEXBUFFER9 vertex_buffer;
|
||||
LPDIRECT3DVERTEXBUFFER9* vertex_ptr;
|
||||
struct pVideoD3D {
|
||||
LPDIRECT3D9 lpd3d = nullptr;
|
||||
LPDIRECT3DDEVICE9 device = nullptr;
|
||||
LPDIRECT3DVERTEXBUFFER9 vertex_buffer = nullptr;
|
||||
LPDIRECT3DVERTEXBUFFER9* vertex_ptr = nullptr;
|
||||
D3DPRESENT_PARAMETERS presentation;
|
||||
D3DSURFACE_DESC d3dsd;
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
D3DRASTER_STATUS d3drs;
|
||||
D3DCAPS9 d3dcaps;
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
LPD3DXEFFECT effect;
|
||||
LPDIRECT3DTEXTURE9 texture = nullptr;
|
||||
LPDIRECT3DSURFACE9 surface = nullptr;
|
||||
LPD3DXEFFECT effect = nullptr;
|
||||
string shader_source_markup;
|
||||
|
||||
bool lost;
|
||||
unsigned iwidth, iheight;
|
||||
bool lost = true;
|
||||
unsigned iwidth;
|
||||
unsigned iheight;
|
||||
|
||||
struct d3dvertex {
|
||||
float x, y, z, rhw; //screen coords
|
||||
@@ -48,9 +48,9 @@ public:
|
||||
} caps;
|
||||
|
||||
struct {
|
||||
HWND handle;
|
||||
bool synchronize;
|
||||
unsigned filter;
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = false;
|
||||
unsigned filter = Video::FilterLinear;
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
@@ -61,7 +61,11 @@ public:
|
||||
unsigned height;
|
||||
} state;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pVideoD3D() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
@@ -69,40 +73,40 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Video::Handle) return (uintptr_t)settings.handle;
|
||||
if(name == Video::Synchronize) return settings.synchronize;
|
||||
if(name == Video::Filter) return settings.filter;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Video::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Video::Handle && value.is<uintptr_t>()) {
|
||||
settings.handle = (HWND)value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(name == Video::Synchronize && value.is<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Filter) {
|
||||
settings.filter = any_cast<unsigned>(value);
|
||||
if(name == Video::Filter && value.is<unsigned>()) {
|
||||
settings.filter = value.get<unsigned>();
|
||||
if(lpd3d) update_filter();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Shader) {
|
||||
if(name == Video::Shader && value.is<string>()) {
|
||||
return false;
|
||||
set_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
//set_shader(value.get<string>());
|
||||
//return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool recover() {
|
||||
auto recover() -> bool {
|
||||
if(!device) return false;
|
||||
|
||||
if(lost) {
|
||||
@@ -142,7 +146,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned rounded_power_of_two(unsigned n) {
|
||||
auto rounded_power_of_two(unsigned n) -> unsigned {
|
||||
n--;
|
||||
n |= n >> 1;
|
||||
n |= n >> 2;
|
||||
@@ -152,7 +156,7 @@ public:
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
void resize(unsigned width, unsigned height) {
|
||||
auto resize(unsigned width, unsigned height) -> void {
|
||||
if(iwidth >= width && iheight >= height) return;
|
||||
|
||||
iwidth = rounded_power_of_two(max(width, iwidth ));
|
||||
@@ -167,7 +171,7 @@ public:
|
||||
device->CreateTexture(iwidth, iheight, 1, flags.t_usage, D3DFMT_X8R8G8B8, (D3DPOOL)flags.t_pool, &texture, NULL);
|
||||
}
|
||||
|
||||
void update_filter() {
|
||||
auto update_filter() -> void {
|
||||
if(!device) return;
|
||||
if(lost && !recover()) return;
|
||||
|
||||
@@ -188,11 +192,11 @@ public:
|
||||
//
|
||||
// (x,y) screen coords, in pixels
|
||||
// (u,v) texture coords, betweeen 0.0 (top, left) to 1.0 (bottom, right)
|
||||
void set_vertex(
|
||||
auto set_vertex(
|
||||
uint32_t px, uint32_t py, uint32_t pw, uint32_t ph,
|
||||
uint32_t tw, uint32_t th,
|
||||
uint32_t x, uint32_t y, uint32_t w, uint32_t h
|
||||
) {
|
||||
) -> void {
|
||||
d3dvertex vertex[4];
|
||||
vertex[0].x = vertex[2].x = (double)(x - 0.5);
|
||||
vertex[1].x = vertex[3].x = (double)(x + w - 0.5);
|
||||
@@ -217,7 +221,7 @@ public:
|
||||
device->SetStreamSource(0, vertex_buffer, 0, sizeof(d3dvertex));
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
if(lost && !recover()) return;
|
||||
|
||||
texture->GetLevelDesc(0, &d3dsd);
|
||||
@@ -236,7 +240,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) {
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
if(lost && !recover()) return false;
|
||||
|
||||
if(width != settings.width || height != settings.height) {
|
||||
@@ -251,13 +255,13 @@ public:
|
||||
return data = (uint32_t*)d3dlr.pBits;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
auto unlock() -> void {
|
||||
surface->UnlockRect();
|
||||
surface->Release();
|
||||
surface = nullptr;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
auto refresh() -> void {
|
||||
if(lost && !recover()) return;
|
||||
|
||||
RECT rd, rs; //dest, source rectangles
|
||||
@@ -333,7 +337,7 @@ public:
|
||||
if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true;
|
||||
}
|
||||
|
||||
void set_shader(const char* source) {
|
||||
auto set_shader(const char* source) -> void {
|
||||
if(!caps.shader) return;
|
||||
|
||||
if(effect) {
|
||||
@@ -347,9 +351,9 @@ public:
|
||||
}
|
||||
shader_source_markup = source;
|
||||
|
||||
XML::Document document(shader_source_markup);
|
||||
bool is_hlsl = document["shader"]["language"].data == "HLSL";
|
||||
string shader_source = document["shader"]["source"].data;
|
||||
auto document = BML::unserialize(shader_source_markup);
|
||||
bool is_hlsl = document["shader"]["language"].text() == "HLSL";
|
||||
string shader_source = document["shader"]["source"].text();
|
||||
if(shader_source == "") return;
|
||||
|
||||
HMODULE d3dx;
|
||||
@@ -373,7 +377,7 @@ public:
|
||||
effect->SetTechnique(hTech);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
RECT rd;
|
||||
@@ -428,32 +432,18 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void release_resources() {
|
||||
auto release_resources() -> void {
|
||||
if(effect) { effect->Release(); effect = 0; }
|
||||
if(vertex_buffer) { vertex_buffer->Release(); vertex_buffer = 0; }
|
||||
if(surface) { surface->Release(); surface = 0; }
|
||||
if(texture) { texture->Release(); texture = 0; }
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
release_resources();
|
||||
if(device) { device->Release(); device = 0; }
|
||||
if(lpd3d) { lpd3d->Release(); lpd3d = 0; }
|
||||
}
|
||||
|
||||
pVideoD3D() {
|
||||
effect = 0;
|
||||
vertex_buffer = 0;
|
||||
surface = 0;
|
||||
texture = 0;
|
||||
device = 0;
|
||||
lpd3d = 0;
|
||||
lost = true;
|
||||
|
||||
settings.handle = 0;
|
||||
settings.synchronize = false;
|
||||
settings.filter = Video::FilterLinear;
|
||||
}
|
||||
};
|
||||
|
||||
DeclareVideo(D3D)
|
||||
|
@@ -2,51 +2,56 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pVideoDD {
|
||||
public:
|
||||
LPDIRECTDRAW lpdd;
|
||||
LPDIRECTDRAW7 lpdd7;
|
||||
LPDIRECTDRAWSURFACE7 screen, raster;
|
||||
LPDIRECTDRAWCLIPPER clipper;
|
||||
struct pVideoDD {
|
||||
LPDIRECTDRAW lpdd = nullptr;
|
||||
LPDIRECTDRAW7 lpdd7 = nullptr;
|
||||
LPDIRECTDRAWSURFACE7 screen = nullptr;
|
||||
LPDIRECTDRAWSURFACE7 raster = nullptr;
|
||||
LPDIRECTDRAWCLIPPER clipper = nullptr;
|
||||
DDSURFACEDESC2 ddsd;
|
||||
DDSCAPS2 ddscaps;
|
||||
unsigned iwidth, iheight;
|
||||
unsigned iwidth;
|
||||
unsigned iheight;
|
||||
|
||||
struct {
|
||||
HWND handle;
|
||||
bool synchronize;
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = false;
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pVideoDD() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Video::Handle) return (uintptr_t)settings.handle;
|
||||
if(name == Video::Synchronize) return settings.synchronize;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Video::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Video::Handle && value.is<uintptr_t>()) {
|
||||
settings.handle = (HWND)value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Synchronize) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(name == Video::Synchronize && value.is<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void resize(unsigned width, unsigned height) {
|
||||
auto resize(unsigned width, unsigned height) -> void {
|
||||
if(iwidth >= width && iheight >= height) return;
|
||||
|
||||
iwidth = max(width, iwidth);
|
||||
@@ -85,7 +90,7 @@ public:
|
||||
if(lpdd7->CreateSurface(&ddsd, &raster, 0) == DD_OK) return clear();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
DDBLTFX fx;
|
||||
fx.dwSize = sizeof(DDBLTFX);
|
||||
fx.dwFillColor = 0x00000000;
|
||||
@@ -93,7 +98,7 @@ public:
|
||||
raster->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
|
||||
}
|
||||
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) {
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
if(width != settings.width || height != settings.height) {
|
||||
resize(settings.width = width, settings.height = height);
|
||||
}
|
||||
@@ -106,11 +111,11 @@ public:
|
||||
return data = (uint32_t*)ddsd.lpSurface;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
auto unlock() -> void {
|
||||
raster->Unlock(0);
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
auto refresh() -> void {
|
||||
if(settings.synchronize) {
|
||||
while(true) {
|
||||
BOOL in_vblank;
|
||||
@@ -134,7 +139,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
DirectDrawCreate(0, &lpdd, 0);
|
||||
@@ -162,23 +167,13 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
if(clipper) { clipper->Release(); clipper = 0; }
|
||||
if(raster) { raster->Release(); raster = 0; }
|
||||
if(screen) { screen->Release(); screen = 0; }
|
||||
if(lpdd7) { lpdd7->Release(); lpdd7 = 0; }
|
||||
if(lpdd) { lpdd->Release(); lpdd = 0; }
|
||||
}
|
||||
|
||||
pVideoDD() {
|
||||
lpdd = 0;
|
||||
lpdd7 = 0;
|
||||
screen = 0;
|
||||
raster = 0;
|
||||
clipper = 0;
|
||||
|
||||
settings.handle = 0;
|
||||
}
|
||||
};
|
||||
|
||||
DeclareVideo(DD)
|
||||
|
@@ -2,40 +2,48 @@
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pVideoGDI {
|
||||
public:
|
||||
uint32_t* buffer;
|
||||
HBITMAP bitmap;
|
||||
HDC bitmapdc;
|
||||
struct pVideoGDI {
|
||||
uint32_t* buffer = nullptr;
|
||||
HBITMAP bitmap = nullptr;
|
||||
HDC bitmapdc = nullptr;
|
||||
BITMAPINFO bmi;
|
||||
|
||||
struct {
|
||||
HWND handle;
|
||||
HWND handle = nullptr;
|
||||
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
pVideoGDI() {
|
||||
buffer = (uint32_t*)memory::allocate(1024 * 1024 * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
~pVideoGDI() {
|
||||
if(buffer) memory::free(buffer);
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Video::Handle) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Video::Handle) return (uintptr_t)settings.handle;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Video::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Video::Handle && value.is<uintptr_t>()) {
|
||||
settings.handle = (HWND)value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) {
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
settings.width = width;
|
||||
settings.height = height;
|
||||
|
||||
@@ -43,11 +51,11 @@ public:
|
||||
return data = buffer;
|
||||
}
|
||||
|
||||
void unlock() {}
|
||||
auto unlock() -> void {}
|
||||
|
||||
void clear() {}
|
||||
auto clear() -> void {}
|
||||
|
||||
void refresh() {
|
||||
auto refresh() -> void {
|
||||
RECT rc;
|
||||
GetClientRect(settings.handle, &rc);
|
||||
|
||||
@@ -57,7 +65,7 @@ public:
|
||||
ReleaseDC(settings.handle, hdc);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
HDC hdc = GetDC(settings.handle);
|
||||
bitmapdc = CreateCompatibleDC(hdc);
|
||||
assert(bitmapdc);
|
||||
@@ -80,19 +88,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
DeleteObject(bitmap);
|
||||
DeleteDC(bitmapdc);
|
||||
}
|
||||
|
||||
pVideoGDI() {
|
||||
buffer = (uint32_t*)malloc(1024 * 1024 * sizeof(uint32_t));
|
||||
settings.handle = 0;
|
||||
}
|
||||
|
||||
~pVideoGDI() {
|
||||
if(buffer) free(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
DeclareVideo(GDI)
|
||||
|
@@ -9,19 +9,23 @@ struct pVideoWGL : OpenGL {
|
||||
HGLRC (APIENTRY* wglCreateContextAttribs)(HDC, HGLRC, const int*) = nullptr;
|
||||
BOOL (APIENTRY* wglSwapInterval)(int) = nullptr;
|
||||
|
||||
HDC display;
|
||||
HGLRC wglcontext;
|
||||
HWND window;
|
||||
HINSTANCE glwindow;
|
||||
HDC display = nullptr;
|
||||
HGLRC wglcontext = nullptr;
|
||||
HWND window = nullptr;
|
||||
HINSTANCE glwindow = nullptr;
|
||||
|
||||
struct {
|
||||
HWND handle;
|
||||
bool synchronize;
|
||||
unsigned filter;
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = false;
|
||||
unsigned filter = Video::FilterNearest;
|
||||
string shader;
|
||||
} settings;
|
||||
|
||||
bool cap(const string& name) {
|
||||
~pVideoWGL() {
|
||||
term();
|
||||
}
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
@@ -29,22 +33,22 @@ struct pVideoWGL : OpenGL {
|
||||
return false;
|
||||
}
|
||||
|
||||
any get(const string& name) {
|
||||
auto get(const string& name) -> any {
|
||||
if(name == Video::Handle) return (uintptr_t)settings.handle;
|
||||
if(name == Video::Synchronize) return settings.synchronize;
|
||||
if(name == Video::Filter) return settings.filter;
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool set(const string& name, const any& value) {
|
||||
if(name == Video::Handle) {
|
||||
settings.handle = (HWND)any_cast<uintptr_t>(value);
|
||||
auto set(const string& name, const any& value) -> bool {
|
||||
if(name == Video::Handle && value.is<uintptr_t>()) {
|
||||
settings.handle = (HWND)value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Synchronize) {
|
||||
if(settings.synchronize != any_cast<bool>(value)) {
|
||||
settings.synchronize = any_cast<bool>(value);
|
||||
if(name == Video::Synchronize && value.is<bool>()) {
|
||||
if(settings.synchronize != value.get<bool>()) {
|
||||
settings.synchronize = value.get<bool>();
|
||||
if(wglcontext) {
|
||||
init();
|
||||
OpenGL::shader(settings.shader);
|
||||
@@ -53,36 +57,36 @@ struct pVideoWGL : OpenGL {
|
||||
}
|
||||
}
|
||||
|
||||
if(name == Video::Filter) {
|
||||
settings.filter = any_cast<unsigned>(value);
|
||||
if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST;
|
||||
if(name == Video::Filter && value.is<unsigned>()) {
|
||||
settings.filter = value.get<unsigned>();
|
||||
if(!settings.shader) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::Shader) {
|
||||
settings.shader = any_cast<const char*>(value);
|
||||
if(name == Video::Shader && value.is<string>()) {
|
||||
settings.shader = value.get<string>();
|
||||
OpenGL::shader(settings.shader);
|
||||
if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST;
|
||||
if(!settings.shader) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) {
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
OpenGL::size(width, height);
|
||||
return OpenGL::lock(data, pitch);
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
auto unlock() -> void {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
auto clear() -> void {
|
||||
OpenGL::clear();
|
||||
SwapBuffers(display);
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
auto refresh() -> void {
|
||||
RECT rc;
|
||||
GetClientRect(settings.handle, &rc);
|
||||
outputWidth = rc.right - rc.left, outputHeight = rc.bottom - rc.top;
|
||||
@@ -90,7 +94,7 @@ struct pVideoWGL : OpenGL {
|
||||
SwapBuffers(display);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
auto init() -> bool {
|
||||
term();
|
||||
|
||||
GLuint pixel_format;
|
||||
@@ -133,26 +137,14 @@ struct pVideoWGL : OpenGL {
|
||||
return true;
|
||||
}
|
||||
|
||||
void term() {
|
||||
auto term() -> void {
|
||||
OpenGL::term();
|
||||
|
||||
if(wglcontext) {
|
||||
wglDeleteContext(wglcontext);
|
||||
wglcontext = 0;
|
||||
wglcontext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
pVideoWGL() {
|
||||
settings.handle = 0;
|
||||
settings.synchronize = false;
|
||||
settings.filter = 0;
|
||||
|
||||
window = 0;
|
||||
wglcontext = 0;
|
||||
glwindow = 0;
|
||||
}
|
||||
|
||||
~pVideoWGL() { term(); }
|
||||
};
|
||||
|
||||
DeclareVideo(WGL)
|
||||
|
Reference in New Issue
Block a user