-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
84 changed files
with
40,280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
#include "stdafx.h" | ||
#include "CEffect.h" | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// Transplant | ||
// Force Feedback Driver for XInput | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
CEffect::CEffect() | ||
:m_Type(FFBEType::ET_NONE) | ||
{ | ||
// status | ||
m_Status = 0; | ||
// View | ||
m_PlayCount = 0; | ||
// Rebirth moment | ||
m_StartTime = 0; | ||
} | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// Calc | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
BOOL CEffect::Calc( | ||
long* LeftLevel | ||
, long* RightLevel | ||
, double CurrentTime) | ||
{ | ||
if (m_Status == FALSE) | ||
return FALSE; | ||
|
||
// Calculate the playback time, start time, end time, and current time of the effect | ||
unsigned long Duration = max(1, m_report.Duration); | ||
double EndTime = DBL_MAX; | ||
if (m_PlayCount != -1 && Duration != 0xFFFF) | ||
{ | ||
EndTime = m_StartTime + (double)Duration * m_PlayCount; | ||
} | ||
|
||
// Is the effect playing? | ||
if (CurrentTime <= EndTime) | ||
{ | ||
|
||
// Calculate the envelope | ||
long NormalRate; | ||
long AttackLevel; | ||
long FadeLevel; | ||
CalcEnvelope( | ||
Duration | ||
, static_cast<ULONG>(CurrentTime - m_StartTime) % Duration | ||
, &NormalRate | ||
, &AttackLevel | ||
, &FadeLevel); | ||
|
||
// Calculate the force | ||
long NormalLevel; | ||
long WorkLeftLevel; | ||
long WorkRightLevel; | ||
CalcForce( | ||
Duration | ||
, static_cast<ULONG>(CurrentTime - m_StartTime) % Duration | ||
, NormalRate | ||
, AttackLevel | ||
, FadeLevel | ||
, &NormalLevel); | ||
|
||
// Adjust the positive and negative of the force | ||
WorkLeftLevel = (NormalLevel > 0) ? NormalLevel : -NormalLevel; | ||
WorkRightLevel = (NormalLevel > 0) ? NormalLevel : -NormalLevel; | ||
|
||
// Adjust the force cap | ||
WorkLeftLevel = min(0xFF, WorkLeftLevel * 0xFF / 10000); | ||
WorkRightLevel = min(0xFF, WorkRightLevel * 0xFF / 10000); | ||
|
||
// Add force | ||
*LeftLevel = *LeftLevel + WorkLeftLevel; | ||
*RightLevel = *RightLevel + WorkRightLevel; | ||
return TRUE; | ||
} | ||
m_Status = FALSE; | ||
return FALSE; | ||
} | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// CalcEnvelope | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
VOID CEffect::CalcEnvelope( | ||
unsigned long Duration | ||
, unsigned long CurrentPos | ||
, long* NormalRate | ||
, long* AttackLevel | ||
, long* FadeLevel) | ||
{ | ||
// Calculate the envelope | ||
if (m_bEnbelope) | ||
{ | ||
// Calculate the rate of attack | ||
long AttackRate = 0; | ||
unsigned long AttackTime = max(1, m_envelope.AttackTime); | ||
if (CurrentPos < AttackTime) | ||
{ | ||
AttackRate = (AttackTime - CurrentPos) * 100 / AttackTime; | ||
} | ||
|
||
// Calculate the percentage of fades | ||
long FadeRate = 0; | ||
unsigned long FadeTime = max(1, m_envelope.FadeTime); | ||
unsigned long FadePos = Duration - FadeTime; | ||
if (FadePos < CurrentPos) | ||
{ | ||
FadeRate = (CurrentPos - FadePos) * 100 / FadeTime; | ||
} | ||
|
||
// Returns the calculated value | ||
*NormalRate = 100 - AttackRate - FadeRate; | ||
*AttackLevel = m_envelope.AttackLevel * AttackRate; | ||
*FadeLevel = m_envelope.FadeLevel * FadeRate; | ||
|
||
} | ||
else | ||
{ | ||
|
||
*NormalRate = 100; | ||
*AttackLevel = 0; | ||
*FadeLevel = 0; | ||
} | ||
} | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// CalcForce | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
VOID CEffect::CalcForce( | ||
unsigned long Duration | ||
, unsigned long CurrentPos | ||
, long NormalRate | ||
, long AttackLevel | ||
, long FadeLevel | ||
, long* NormalLevel) | ||
{ | ||
long Magnitude = 0; | ||
long Period; | ||
long R; | ||
long Rate; | ||
|
||
FFBEType type = m_Type == FFBEType::ET_NONE ? m_report.EffectType : m_Type; | ||
|
||
// Sort processing according to the type of effect | ||
switch (type) | ||
{ | ||
case ET_SPRNG: | ||
case ET_DMPR: | ||
case ET_INRT: | ||
case ET_FRCTN: | ||
; | ||
break; | ||
|
||
// Constant force | ||
case ET_CONST: | ||
// Find the magnitude considering the envelope | ||
Magnitude = m_constantForce.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
break; | ||
|
||
// Custom force | ||
case ET_CSTM: | ||
; | ||
break; | ||
|
||
// Periodic effect | ||
case ET_SQR: | ||
|
||
// Find somewhere between 0 and 359 degrees from the time (milliseconds) and elapsed time of one cycle. | ||
Period = max(1, m_periodic.Period); | ||
R = (CurrentPos % Period) * 360 / Period; | ||
|
||
// Calculate the phase | ||
R = (R + (m_periodic.Phase / 100)) % 360; | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = m_periodic.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
|
||
// Find the magnitude considering the square | ||
if (180 <= R) | ||
{ | ||
Magnitude = Magnitude * -1; | ||
} | ||
|
||
// Calculate the offset | ||
Magnitude = Magnitude + m_periodic.Offset; | ||
break; | ||
|
||
case ET_SINE: | ||
|
||
// Find somewhere between 0 and 359 degrees from the time (milliseconds) and elapsed time of one cycle. | ||
Period = max(1, m_periodic.Period); | ||
R = (CurrentPos % Period) * 360 / Period; | ||
|
||
// Calculate the phase | ||
R = (R + (m_periodic.Phase / 100)) % 360; | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = m_periodic.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
|
||
// Find the magnitude considering the square | ||
Magnitude = static_cast<LONG>(Magnitude * sin(R * 3.1415 / 180.0)); | ||
|
||
// Calculate the offset | ||
Magnitude = Magnitude + m_periodic.Offset; | ||
break; | ||
|
||
case ET_TRNGL: | ||
|
||
// Find somewhere between 0 and 359 degrees from the time (milliseconds) and elapsed time of one cycle. | ||
Period = max(1, m_periodic.Period); | ||
R = (CurrentPos % Period) * 360 / Period; | ||
|
||
// Calculate the phase | ||
R = (R + (m_periodic.Phase / 100)) % 360; | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = m_periodic.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
|
||
// Find the magnitude considering the triangular wave | ||
if (0 <= R && R < 90) | ||
{ | ||
Magnitude = -Magnitude * (90 - R) / 90; | ||
} | ||
if (90 <= R && R < 180) | ||
{ | ||
Magnitude = Magnitude * (R - 90) / 90; | ||
} | ||
if (180 <= R && R < 270) | ||
{ | ||
Magnitude = Magnitude * (90 - (R - 180)) / 90; | ||
} | ||
if (270 <= R && R < 360) | ||
{ | ||
Magnitude = -Magnitude * (R - 270) / 90; | ||
} | ||
// Calculate the offset | ||
Magnitude = Magnitude + m_periodic.Offset; | ||
break; | ||
|
||
case ET_STUP: | ||
|
||
// Find somewhere between 0 and 359 degrees from the time (milliseconds) and elapsed time of one cycle. | ||
Period = max(1, m_periodic.Period); | ||
R = (CurrentPos % Period) * 360 / Period; | ||
|
||
// Calculate the phase | ||
R = (R + (m_periodic.Phase / 100)) % 360; | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = m_periodic.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
|
||
// Finding a magnitude that takes up saw teeth into consideration | ||
if (0 <= R && R < 180) | ||
{ | ||
Magnitude = -Magnitude * (180 - R) / 180; | ||
} | ||
if (180 <= R && R < 360) | ||
{ | ||
Magnitude = Magnitude * (R - 180) / 180; | ||
} | ||
|
||
// Calculate the offset | ||
Magnitude = Magnitude + m_periodic.Offset; | ||
break; | ||
|
||
case ET_STDN: | ||
|
||
// Find somewhere between 0 and 359 degrees from the time (milliseconds) and elapsed time of one cycle. | ||
Period = max(1, m_periodic.Period); | ||
R = (CurrentPos % Period) * 360 / Period; | ||
|
||
// Calculate the phase | ||
R = (R + (m_periodic.Phase / 100)) % 360; | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = m_periodic.Magnitude; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
|
||
// Finding a magnitude that takes down feathers into consideration | ||
if (0 <= R && R < 180) | ||
{ | ||
Magnitude = Magnitude * (180 - R) / 180; | ||
} | ||
if (180 <= R && R < 360) | ||
{ | ||
Magnitude = -Magnitude * (R - 180) / 180; | ||
} | ||
|
||
// Calculate the offset | ||
Magnitude = Magnitude + m_periodic.Offset; | ||
break; | ||
|
||
// Inclined force | ||
case ET_RAMP: | ||
|
||
// Calculate the ratio of start point and end point | ||
Rate = (Duration - CurrentPos) * 100 | ||
/ max(1, m_report.Duration); | ||
|
||
// Find the magnitude considering the envelope | ||
Magnitude = (m_rampForce.Start * Rate | ||
+ m_rampForce.End * (100 - Rate)) / 100; | ||
Magnitude = (Magnitude * NormalRate + AttackLevel + FadeLevel) / 100; | ||
break; | ||
} | ||
|
||
// Returns a force that takes gain into account | ||
*NormalLevel = Magnitude * m_report.Gain / 0xFF; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#pragma once | ||
|
||
//---------------------------------------------------------------------------------------------- | ||
// Transplant | ||
// Force Feedback Driver for XInput | ||
//---------------------------------------------------------------------------------------------- | ||
|
||
class CEffect | ||
{ | ||
public: | ||
// Constructor | ||
CEffect(); | ||
|
||
// Calculate the effect | ||
BOOL Calc(LONG*, LONG*, double CurrentTime); | ||
|
||
// Type | ||
FFBEType m_Type; | ||
// DIEFFECT | ||
FFB_EFF_REPORT m_report = { 0 }; | ||
|
||
// DIENVELOPE | ||
FFB_EFF_ENVLP m_envelope = { 0 }; | ||
bool m_bEnbelope; | ||
|
||
// DICONSTANTFORCE | ||
FFB_EFF_CONSTANT m_constantForce = { 0 }; | ||
|
||
// DIPERIODIC | ||
FFB_EFF_PERIOD m_periodic = { 0 }; | ||
|
||
// DIRAMPFORCE | ||
FFB_EFF_RAMP m_rampForce = { 0 }; | ||
|
||
// status | ||
DWORD m_Status; | ||
// View | ||
unsigned long m_PlayCount; | ||
// Rebirth moment | ||
double m_StartTime; | ||
|
||
private: | ||
// Calculate the envelope | ||
VOID CalcEnvelope(ULONG, ULONG, LONG*, LONG*, LONG*); | ||
// Calculate the force | ||
VOID CalcForce(ULONG, ULONG, LONG, LONG, LONG, LONG*); | ||
|
||
protected: | ||
}; |
Oops, something went wrong.