Skip to content

Commit

Permalink
振動サポート
Browse files Browse the repository at this point in the history
「XInput 用フォース フィードバック ドライバ」から移植
  • Loading branch information
090 committed May 11, 2016
1 parent 17f11d8 commit 5c3744c
Show file tree
Hide file tree
Showing 9 changed files with 639 additions and 52 deletions.
6 changes: 3 additions & 3 deletions ds4vjoy/DS4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ void DS4Device::InputLoop()
LogPrintf(L"通信を開始します。");
firstflag = false;
}
Sleep(1);
}
m_threadShutdown = true;

Expand All @@ -270,15 +269,16 @@ void DS4Device::InputLoop()
void DS4Device::OutputLoop()
{
while (!m_threadShutdown) {
if (m_write_count != m_write_count2) {
while (m_write_count != m_write_count2) {
m_write_count2 = m_write_count;
if (!_write()) {
break;
goto EndOutputLoop;
}
}
std::unique_lock<std::mutex> lk(m_write_mutex);
m_write_cv.wait(lk);
}
EndOutputLoop:
m_threadShutdown = true;

}
Expand Down
234 changes: 234 additions & 0 deletions ds4vjoy/FFB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
//移植
#include "stdafx.h"
#include "FFB.h"

void FFB::callback(PVOID data, PVOID userdata)
{
if (userdata == 0)
return;
FFB *ffb = (FFB*)userdata;
ffb->_callback((FFB_DATA *)data);
}

void FFB::_callback(FFB_DATA *data)
{

FFBPType Type;
if (ERROR_SUCCESS != Ffb_h_Type(data, &Type))
return;
int BlockIndex=-1;
Ffb_h_EBI(data, &BlockIndex);

CEffect * effect=NULL;
if(BlockIndex!=-1)
effect = &m_effects[BlockIndex];
std::lock_guard<std::mutex> lock(m_mutex);

switch (Type)
{
case PT_EFFREP:
#pragma warning( push )
#pragma warning( disable : 4996 )
if (ERROR_SUCCESS != Ffb_h_Eff_Report(data, &effect->m_report))
break;
#pragma warning( pop )
break;
case PT_ENVREP:
if (ERROR_SUCCESS != Ffb_h_Eff_Envlp(data, &effect->m_envelope))
break;
effect->m_bEnbelope = true;
effect->m_envelope.AttackLevel = static_cast<LONG>(static_cast<__int16>(effect->m_envelope.AttackLevel));
effect->m_envelope.FadeLevel = static_cast<LONG>(static_cast<__int16>(effect->m_envelope.FadeLevel));
break;
case PT_CONDREP:
//Condition Report
break;
case PT_PRIDREP:
if (ERROR_SUCCESS != Ffb_h_Eff_Period(data, &effect->m_periodic))
break;
effect->m_periodic.Offset = static_cast<LONG>(static_cast<__int16>(effect->m_periodic.Offset));
break;
case PT_CONSTREP:
if (ERROR_SUCCESS != Ffb_h_Eff_Constant(data, &effect->m_constantForce))
break;
effect->m_constantForce.Magnitude = static_cast<LONG>(static_cast<__int16>(effect->m_constantForce.Magnitude));
break;
case PT_RAMPREP:
if (ERROR_SUCCESS != Ffb_h_Eff_Ramp(data, &effect->m_rampForce))
break;
effect->m_rampForce.Start = static_cast<LONG>(static_cast<__int16>(effect->m_rampForce.Start));
effect->m_rampForce.End = static_cast<LONG>(static_cast<__int16>(effect->m_rampForce.End));
break;
case PT_CSTMREP:
//Custom Force Data Report
break;
case PT_SMPLREP:
//-Download Force Sample
break;
case PT_EFOPREP:
//Effect Operation Report
_operation(data);
break;
case PT_BLKFRREP:
//PID Block Free Report
m_effects.erase(BlockIndex);
break;
case PT_CTRLREP:
//-PID Device Contro
_ctrl(data);
break;
case PT_GAINREP:
//-Device Gain Report
if (ERROR_SUCCESS != Ffb_h_DevGain(data, &m_Gain))
break;
break;
case PT_SETCREP:
//Set Custom Force Report
break;
case PT_NEWEFREP:
{
/*
CEffect neweffect;
if (ERROR_SUCCESS != Ffb_h_EffNew(data, &neweffect.m_Type))
break;
*/
break;
}
case PT_BLKLDREP:
//Block Load Report
break;
case PT_POOLREP:
//-PID Pool Report
break;
}

}

void FFB::_ctrl(FFB_DATA *data)
{
FFB_CTRL control;
if (ERROR_SUCCESS != Ffb_h_DevCtrl(data, &control))
return;
switch (control)
{
case CTRL_ENACT:
//アクチュエータを有効にするEnable Actuators
m_bActuator = true;
break;
case CTRL_DISACT:
//アクチュエータを無効にするDisable Actuators
m_bActuator = false;
break;
case CTRL_STOPALL:
//全てのエフェクトの再生を停止するStop All Effects
for (auto &kv : m_effects) {
kv.second.m_Status = FALSE;
}
break;
case CTRL_DEVRST:
//全てのエフェクトを削除するDevice Reset
m_effects.clear();
break;
case CTRL_DEVPAUSE:
//再生を一時停止するDevice Pause
for (auto &kv : m_effects) {
kv.second.m_Status = FALSE;
}
m_bPaused = true;
m_dwPausedTime = getTime();
break;
case CTRL_DEVCONT:
//一時停止を解除するDevice Continue
if (m_bPaused) {
m_dwPausedTime = getTime() - m_dwPausedTime;
for (auto &kv : m_effects) {
if (kv.second.m_Status == FALSE) {
kv.second.m_StartTime += m_dwPausedTime;
kv.second.m_Status = TRUE;
}
}
m_bPaused = false;
}
break;
}
}

void FFB::_operation(FFB_DATA *data)
{
FFB_EFF_OP op;
if (ERROR_SUCCESS != Ffb_h_EffOp(data, &op))
return;
CEffect*effect = &m_effects[op.EffectBlockIndex];
switch (op.EffectOp)
{
case EFF_SOLO:
//Effect Solo Start
for (auto &kv : m_effects) {
kv.second.m_Status = FALSE;
}
case EFF_START:
//Effect Start
effect->m_StartTime = getTime();
effect->m_Status = TRUE;
effect->m_PlayCount = op.LoopCount;
m_bStoped = false;
m_bPaused = false;
break;
case EFF_STOP:
//Effect Stop
effect->m_Status = FALSE;
break;
}
}

double FFB::getTime()
{
LARGE_INTEGER t;
QueryPerformanceCounter(&t);
return (double)(t.QuadPart - m_gt_start.QuadPart) / m_gt_ms;
}



bool FFB::Calc(BYTE * _left, BYTE * _right)
{
LONG left = 0, right = 0;
if (m_bActuator && !m_bStoped && !m_bPaused) {
bool playing = false;
double currentTime = getTime();
std::lock_guard<std::mutex> lock(m_mutex);
for (auto &kv : m_effects) {
if (kv.second.Calc(&left, &right, currentTime))
playing = true;
}
if (!playing) {
m_bStoped = true;
}
if (left > 0xFF) left = 0xFF;
if (right > 0xFF) right = 0xFF;
left = left * m_Gain / 0xFF;
right = right * m_Gain / 0xFF;
}
if (m_lastLeft != left || m_lastRight != right) {
*_left = m_lastLeft = static_cast<BYTE>(left);
*_right = m_lastRight = static_cast<BYTE>(right);
return true;
}
return false;
}

FFB::FFB()
:m_bActuator(true)
,m_bPaused(false)
,m_bStoped(true)
,m_Gain(0xFF)
{
LARGE_INTEGER f;
QueryPerformanceFrequency(&f);
m_gt_ms = static_cast<double>(f.QuadPart) / 1000.0;
QueryPerformanceCounter(&m_gt_start);
}

FFB::~FFB()
{
}
27 changes: 27 additions & 0 deletions ds4vjoy/FFB.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include "ffb/effect.h"
class FFB
{
std::map<int,CEffect> m_effects;
void CALLBACK _callback(FFB_DATA *data);
void _ctrl(FFB_DATA*);
void _operation(FFB_DATA*);
bool m_bActuator;
bool m_bStoped;
bool m_bPaused;
double m_dwPausedTime;
BYTE m_Gain;
double getTime();
LARGE_INTEGER m_gt_start;
double m_gt_ms;

std::mutex m_mutex;
BYTE m_lastLeft,m_lastRight;
public:
static void CALLBACK callback(PVOID , PVOID );

bool Calc(BYTE *left, BYTE *right);
FFB();
~FFB();
};

64 changes: 15 additions & 49 deletions ds4vjoy/ds4vjoy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "ds4vjoy.h"
#include "DS4.h"
#include "vjoy.h"
#include "FFB.h"
#include "Stopwatch.h"

#include "Settings.h"
Expand Down Expand Up @@ -153,12 +154,23 @@ typedef struct _ds4cbParams
int splitRow;
int splitButton;
Stopwatch sw;
FFB ffb;
double ffb_time;
} DS4cbParams;

void ds4inputcb(DS4Device * ds4, BOOL updateflag,void*param) {
double now;
DS4cbParams *p = (DS4cbParams*)param;
p->sw.Lap(&now);
if (p->ffb_time + 3 < now) {//3ms
BYTE left, right;
if (p->ffb.Calc(&left, &right)) {
ds4->SetMoter(left, right);
ds4->Write();
}
p->ffb_time = now;
}


if (updateflag == false && p->rapidFireflag == false)
return;
Expand Down Expand Up @@ -212,53 +224,6 @@ void ds4inputcb(DS4Device * ds4, BOOL updateflag,void*param) {

}

//手抜き振動処理
int TwosCompWord2Int(WORD in)
{
int tmp;
WORD inv = ~in;
BOOL isNeg = in >> 15;
if (isNeg)
{
tmp = (int)(inv);
tmp = -1 * tmp;
return tmp - 1;
}
else
return (int)in;
}
void CALLBACK ffbCallback(PVOID data, PVOID userdata)
{
DS4cbParams *p = (DS4cbParams*)userdata;
int devid;
if (ERROR_SUCCESS != Ffb_h_DeviceID((FFB_DATA *)data, &devid))
return;
if (devid != p->vJoyDevID)
return;

FFB_EFF_CONSTANT ConstantEffect;
if (ERROR_SUCCESS != Ffb_h_Eff_Constant((FFB_DATA *)data, &ConstantEffect))
return;

ConstantEffect.Magnitude = TwosCompWord2Int((WORD)ConstantEffect.Magnitude);

if (ConstantEffect.Magnitude < 0) {
ConstantEffect.Magnitude = -ConstantEffect.Magnitude;
}

static int lastMagnitude = 10001;
if (lastMagnitude == ConstantEffect.Magnitude)
return;
lastMagnitude = ConstantEffect.Magnitude;

if (p->ds4->Active()) {
BYTE motor = (BYTE) ((double)ConstantEffect.Magnitude / 10000.0 * 255);
p->ds4->SetMoter(motor, motor);
p->ds4->Write();
}
}



LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
Expand Down Expand Up @@ -330,7 +295,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
SendMessage(hStatus, SB_SETTEXT, 0 | 0, (WPARAM)L"待機");
}

LogPrintf(L"DS4vJoy Ver1.0");
LogPrintf(L"DS4vJoy Ver1.1");

//vjoy初期化
if (!vjoy.Init(hWnd)) {
Expand Down Expand Up @@ -396,7 +361,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (vjoy.Open(g_settings.vJoyDeviceID)) {
cbParams.vJoyDevID = g_settings.vJoyDeviceID;
if (g_settings.FFB) {
vjoy.SetFFBCallback(ffbCallback, &cbParams);
cbParams.ffb_time = 0;
vjoy.SetFFBCallback(cbParams.ffb.callback, &cbParams.ffb);
}
else {
vjoy.SetFFBCallback(NULL, NULL);
Expand Down
Binary file modified ds4vjoy/ds4vjoy.rc
Binary file not shown.
Loading

0 comments on commit 5c3744c

Please sign in to comment.