DX7RUMBLE - beta 1 - By: Todd Riggins aka: Pepsi - FREEWARE!

Legal: Microsoft, MS-DOS, Windows, Windows NT, Direct3D, DirectAnimation, DirectDraw, DirectInput, DirectMusic, DirectPlay, DirectShow, DirectSound, DirectX, Visual C++, Visual Studio, Win32, Xbox, Xbox 360 and XNA are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

Features:
- Allows you to access DirectX 7's DirectInput game device controls and FORCE FEEDBACK!
- Created to use DirectX 7's technology to keep it the same level as what Blitz3D uses.
- Create FFB Effects.
- Create Envelopes to further manipulate effects.
- Update effects on-the-fly to react to game conditions.
- Enumerates all windows registered game devices that are currently connected.
- Get game device names and the regular button/axle/pov/slider info.
- Set range, saturation and deadzones to fine tune a game device incoming data.
- FREEWARE!


Instructions:
- Put decls in userlib directory.
- Put dll your program's directory.
- Explore the demo's example source code to get the feel of it.
- ( The DX7 sdk documentation on force feedback will help you better understand more than I can ever teach you or tell you about it! )
- Ask questions about it on the blitzbasic forum. Unless you think you found a bug, someone else may know how to use this better than me. I say this as I am no expert at FFB usage in general. I have only tried my best to supply you with solid, clean DX7 Input Game Device & FFB function accessibility.
- Make games with FFB Effects!

How to use?
- Firstly, please forgive me that I'm not a good documentation writer.
- I will try to give enough detail info for each command description.
- Call DX7RUMBLE_INIT to initialize the dll and to get it ready for use. You will need to supply the first two params with the Window handle and the DirectInput7 interface that blitz supplies you with via it's SystemProperty command. The last param is a boolean allowing you to turn dll debugging on or off. When it's on, it will create a debug file in the same folder the dll is in which it will write info/errors to.
- Call DX7RUMBLE_RELEASE at the end of your program to release any memory used by the dll itself! If you dont, memory leaks will happen.
- Call DX7RUMBLE_POLL inside of the beginning of your game loop to update game device info.
- Use the value that the TOTAL_GAMEDEVICES command minus one to loop through each gamedevice you have installed to get info from.
- Call FFB_AVAIL to check to see if the specified game device supports FFB or not.
- All of the JOY_* commands that dont have "RANGE", "SATURATION" or "DEADZONE" at the end of its name returns info that the user has/hasn't done with the game device during runtime.
- All of the JOY_* commands that DO have "RANGE", "SATURATION" or "DEADZONE" at the end of its name allows you to fine tune/set boundaries on the data returned by the specified game device.
- EFFECTS: when you create them, they are not attached to any paticular game device yet until you use the ATTACH_EFFECT command.
- You can use the PLAY_EFFECT command to play them at anytime you want(example: a button hit, ship hits a wall, etc...).
- Using the SET_EFFECT_* commands allows you to customize your own effect after when you first create an effect with the CREATE_EFFECT command.
- You have four effect styles you can make by using the respective SET_EFFECT_* command. ( ie: CONSTANTFORCE, PERIODIC, RAMPFORCE and CONDITION ). Note: you can NOT use more the one effect style per effect.
- You can also call CREATE_ENVELOPE to supply an envelope to a CONSTANTFORCE, PERIODIC and RAMPFORCE effect style to futher customize how the effect plays. Note: you can not use envelope on a CONDITION effect style.
- When you want to change an effect dynamically during runtime, call the CLEAR_EFFECT command on the specific effect you want to change first. After that, use specific SET_EFFECT_* commands to change only what you want to change on the effect. Then after that, call the UPDATE_EFFECT to change the effect while it's playing. You will have to flag boolean style parameters of the UPDATE_EFFECT command to let the dll know what you are changing in the effect itself.
- Hopefully, that will get you started. Please read the documentation below. If you have the DX7 sdk documentation it will help you understand this stuff even better.
- Again explore the demo example's source code to see how it's used.
- Good luck and have fun with it!

 
DX7RUMBLE_INIT
DX7RUMBLE_RELEASE
DX7RUMBLE_POLL
TOTAL_GAMEDEVICES
TOTAL_EFFECTS
TOTAL_ENVELOPES
GAMEDEVICE_NAME
GAMEDEVICE_REAQUIRE
GAMEDEVICE_RUNCONTROLPANEL
FFB_AVAIL
FFB_AUTOCENTER
JOY_X_AXIS
JOY_Y_AXIS
JOY_Z_AXIS
JOY_RX_AXIS
JOY_RY_AXIS
JOY_RZ_AXIS
JOY_SLIDER
JOY_POV
JOY_BUTTON
JOY_VX_AXIS
JOY_VY_AXIS
JOY_VZ_AXIS
JOY_VRX_AXIS
JOY_VRY_AXIS
JOY_VRZ_AXIS
JOY_VSLIDER
JOY_AX_AXIS
JOY_AY_AXIS
JOY_AZ_AXIS
JOY_ARX_AXIS
JOY_ARY_AXIS
JOY_ARZ_AXIS
JOY_ASLIDER
JOY_FX_AXIS
JOY_FY_AXIS
JOY_FZ_AXIS
JOY_FRX_AXIS
JOY_FRY_AXIS
JOY_FRZ_AXIS
JOY_FSLIDER
JOY_X_RANGE
JOY_Y_RANGE
JOY_Z_RANGE
JOY_RX_RANGE
JOY_RY_RANGE
JOY_RZ_RANGE
JOY_SLIDER_RANGE
JOY_X_DEADZONE
JOY_Y_DEADZONE
JOY_Z_DEADZONE
JOY_RX_DEADZONE
JOY_RY_DEADZONE
JOY_RZ_DEADZONE
JOY_SLIDER_DEADZONE
JOY_X_SATURATION
JOY_Y_SATURATION
JOY_Z_SATURATION
JOY_RX_SATURATION
JOY_RY_SATURATION
JOY_RZ_SATURATION
JOY_SLIDER_SATURATION
CREATE_EFFECT
SET_EFFECT_AXES
SET_EFFECT_DURATION
SET_EFFECT_SAMPLEPERIOD
SET_EFFECT_GAIN
SET_EFFECT_CONSTANTFORCE
SET_EFFECT_PERIODIC
SET_EFFECT_RAMPFORCE
SET_EFFECT_CONDITION
CREATE_ENVELOPE
ATTACH_EFFECT
PLAY_EFFECT
STOP_EFFECT
UNATTACH_EFFECT
CLEAR_EFFECT
UPDATE_EFFECT
HAS_DYNAMIC_EFFECT_SUPPORT
HAS_EFFECT_SUPPORT

 
^| DX7RUMBLE_INIT%(hwnd%, LPDIRECTINPUT7%, debugmode%)
  • hwnd% = window handle.
  • LPDIRECTINPUT7% = DirectX 7's DirectInput Interface pointer.
  • debugmode% = Set a true/false boolean value to turn dll debug mode on or off.
  • Return Value: 1 = Successful, 0 = Failed
DX7RUMBLE_INIT should be called once somewhere in your setup/startup code. This initializes the DX7Rumble.dll to get ready for working with the DirectX 7's DirectInput game device and force feedback functionality. Please make sure the DX7RUMBLE_RELEASE command gets called before your application ends. This will free up any memory that the DX7RUMBLE_INIT command has created.

Use the return value of SystemProperty$("AppHWND") to get blitz's window handle. Use the return value of SystemProperty$("DirectInput7") to get the pointer the DirectX 7's DirectInput Interface. When setting a true value for the debugmode parameter, a "dx7rumble_debug.txt" file will be created in the same folder as the dll used is in and debug information will be written to it.


^| DX7RUMBLE_RELEASE()
  • [no params]
  • Return Value: na
Call this command at the end of your application to make sure whatever memory that DX7RUMBLE_INIT used gets released. If you dont, then you will have memory leaks!


^| DX7RUMBLE_POLL()
  • [no params]
  • Return Value: na
Call this command somewhere inside the beggining of your game loop to allow DirectInput to update game device data.


^| TOTAL_GAMEDEVICES%()
  • [no params]
  • Return Value: Total number of game devices available.
This command will return the total amount of game devices that windows itself can see as available. You can also see if your game device is available in windows by running your windows control panel->game devices application.

Note: when accessing game devices through various commands, you will need to use the zero base system. (ie: 0 to TOTAL_GAMEDEVICES-1)


^| TOTAL_EFFECTS%()
  • [no params]
  • Return Value: Total number of effects that have been created.
When you call CREATE_EFFECT to create an effect, an internal dll value increments by 1. This command simply returns that value.


^| TOTAL_ENVELOPES%()
  • [no params]
  • Return Value: Total number of envelopes that have been created
When you call CREATE_ENVELOPE to create an envelope, an internal dll value increments by 1. This command simply returns that value.

Note: A single envelope is created when first initializing the dll with DX7RUMBLE_INIT. So, if you call this command without you creating any envelopes, you will get a return value of 1. This dll created envelope is used as a NULL envelope. See SET_EFFECT_CONSTANTFORCE, SET_EFFECT_PERIODIC and SET_EFFECT_RAMPFORCE for more detail about this "NULL envelope" usage.


^| GAMEDEVICE_NAME$(joynum%)
  • joynum% = game device number
  • Return Value: Name of the game device
Call this command when you want to get the name any game device that is currently available.


^| GAMEDEVICE_REAQUIRE(joynum%)
  • joynum% = game device number
  • Return Value:
If you are not getting data from your game device, call this command to reaquire the game device.


^| GAMEDEVICE_RUNCONTROLPANEL%(joynum%)
  • joynum% = game device number
  • Return Value: 1 = Successful, 0 = Failed
Call this command to run the DirectInput control panel associated with the specified game device. If the game device does not have a control panel associated with it, the default device control panel is launched.


^| FFB_AVAIL%(joynum%)
  • joynum% = game device number
  • Return Value: 1 = FFB is available, 0 = FFB is NOT available
Call this command to see if Force FeedBack is available or not for the specified game device.


^| FFB_AUTOCENTER%(joynum%,bOnOff%)
  • joynum% = game device number
  • bOnOff% = A boolean value to turn on or off the autocentering.
  • Return Value: 1 = Successful, 0 = Failed
Call this command to specify whether the specified game device is to be self-centering. Not all game devices support auto centering. Also, the use of force feedback effects can interfere with the auto centering spring. Some game devices even disable the auto centering when effects are played. If you are NOT using force feedback effects, turn auto centering on so force feedback enabled game devices (ie: joysticks for an example ) can auto center.

Pass a value of 0 in the bOnOff% parameter to tell the game device to not to automatically center when the user releases the game device.
Pass a value of 1 in the bOnOff% parameter to tell the game device it should automatically center when the user releases the game device.


^| JOY_X_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis value


^| JOY_Y_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis value


^| JOY_Z_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis value


^| JOY_RX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis rotation value


^| JOY_RY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis rotation value


^| JOY_RZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis rotation value


^| JOY_SLIDER%(joynum%,num%)
  • joynum% = game device number
  • num% = specify slider number 0-1
  • Return Value: current slider value


^| JOY_POV%(joynum%,num%)
  • joynum% = game device number
  • num% = specify POV hat number 0-3
  • Return Value: current pov value
Note: The current pov value is indicated in hundredths of a degree clockwise from north (away from the user). The center position is reported as –1. Possible POV values for a controller is –1, 0, 9000, 18000, or 27000.


^| JOY_BUTTON%(joynum%,num%)
  • joynum% = game device number
  • num% = specify button number 0-127
  • Return Value: current button value
Note: the return value will return 0 for button not being pressed or a value of 1 if the button is being pressed.


^| JOY_VX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis velocity value


^| JOY_VY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis velocity value


^| JOY_VZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis velocity value


^| JOY_VRX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis angular velocity value


^| JOY_VRY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis angular velocity value


^| JOY_VRZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis angular velocity value


^| JOY_VSLIDER%(joynum%,num%)
  • joynum% = game device number
  • num% = specify vslider number 0-1
  • Return Value: current slider velocity value


^| JOY_AX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis acceleration value


^| JOY_AY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis acceleration value


^| JOY_AZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis acceleration value


^| JOY_ARX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis angular acceleration value


^| JOY_ARY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis angular acceleration value


^| JOY_ARZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis angular acceleration value


^| JOY_ASLIDER%(joynum%,num%)
  • joynum% = game device number
  • num% = specify aslider number 0-1
  • Return Value: current slider acceleration value


^| JOY_FX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis force value


^| JOY_FY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis force value


^| JOY_FZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis force value


^| JOY_FRX_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current x axis torque value


^| JOY_FRY_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current y axis torque value


^| JOY_FRZ_AXIS%(joynum%)
  • joynum% = game device number
  • Return Value: current z axis torque value


^| JOY_FSLIDER%(joynum%,num%)
  • joynum% = game device number
  • num% = specify fslider number 0-1
  • Return Value: current slider force value


^| JOY_X_RANGE(joynum%, Xmin%, Xmax% )
  • joynum% = game device number
  • Xmin% = set minimum x range
  • Xmax% = set maximum x range
  • Return Value: na
Call this command to set the furthest range min/max x values the game device can report.


^| JOY_Y_RANGE(joynum%, Ymin%, Ymax% )
  • joynum% = game device number
  • Ymin% = set minimum y range
  • Ymax% = set maximum y range
  • Return Value: na
Call this command to set the furthest range min/max y values the game device can report.


^| JOY_Z_RANGE(joynum%, Zmin%, Zmax% )
  • joynum% = game device number
  • Zmin% = set minimum z range
  • Zmax% = set maximum z range
  • Return Value: na
Call this command to set the furthest range min/max z values the game device can report.


^| JOY_RX_RANGE(joynum%, RXmin%, RXmax% )
  • joynum% = game device number
  • RXmin% = set minimum x axis rotation range
  • RXmax% = set maximum x axis rotation range
  • Return Value: na
Call this command to set the furthest range min/max x axis rotation values the game device can report.


^| JOY_RY_RANGE(joynum%, RYmin%, RYmax% )
  • joynum% = game device number
  • RYmin% = set minimum y axis rotation range
  • RYmax% = set maximum y axis rotation range
  • Return Value: na
Call this command to set the furthest range min/max y axis rotation values the game device can report.


^| JOY_RZ_RANGE(joynum%, RZmin%, RZmax% )
  • joynum% = game device number
  • RZmin% = set minimum z axis rotation range
  • RZmax% = set maximum z axis rotation range
  • Return Value: na
Call this command to set the furthest range min/max z axis rotation values the game device can report.


^| JOY_SLIDER_RANGE(joynum%, num%, Smin%, Smax% )
  • joynum% = game device number
  • num% = specify slider number 0-1
  • Smin% = set minimum slider range
  • Smax% = set maximum slider range
  • Return Value: na
Call this command to set the furthest range min/max slider values the game device can report.


^| JOY_X_DEADZONE(joynum%, Xzone% )
  • joynum% = game device number
  • Xzone% = set x axis deadzone
  • Return Value: na
Sets the x axis value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_Y_DEADZONE(joynum%, Yzone% )
  • joynum% = game device number
  • Xzone% = set y axis deadzone
  • Return Value: na
Sets the y axis value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_Z_DEADZONE(joynum%, Zzone% )
  • joynum% = game device number
  • Xzone% = set z axis deadzone
  • Return Value: na
Sets the z axis value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_RX_DEADZONE(joynum%, RXzone% )
  • joynum% = game device number
  • Xzone% = set x axis rotation deadzone
  • Return Value: na
Sets the x axis rotation value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_RY_DEADZONE(joynum%, RYzone% )
  • joynum% = game device number
  • Xzone% = set y axis rotation deadzone
  • Return Value: na
Sets the y axis rotation value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_RZ_DEADZONE(joynum%, RZzone% )
  • joynum% = game device number
  • Xzone% = set z axis rotation deadzone
  • Return Value: na
Sets the z axis rotation value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_SLIDER_DEADZONE(joynum%, num%, Slider_zone% )
  • joynum% = game device number
  • num% = specify slider number 0-1
  • Slider_zone% = set the slider deadzone
  • Return Value: na
Sets the slider value for the dead zone of the game device. Using a range from 0 through 10000, 0 indicates that there is no dead zone, 5000 indicates that the dead zone extends over 50 percent of the physical range of the axis on both sides of center, and 10000 indicates that the entire physical range of the axis is dead. When the axis is within the dead zone, it is reported as being at the center of its range.


^| JOY_X_SATURATION(joynum%, Xsat% )
  • joynum% = game device number
  • Xsat% = set x axis saturation
  • Return Value: na
Sets the x axis value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_Y_SATURATION(joynum%, Ysat% )
  • joynum% = game device number
  • Ysat% = set y axis saturation
  • Return Value: na
Sets the y axis value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_Z_SATURATION(joynum%, Zsat% )
  • joynum% = game device number
  • Zsat% = set z axis saturation
  • Return Value: na
Sets the z axis value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_RX_SATURATION(joynum%, RXsat% )
  • joynum% = game device number
  • RXsat% = set x axis rotation saturation
  • Return Value: na
Sets the x axis rotation value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_RY_SATURATION(joynum%, RYsat% )
  • joynum% = game device number
  • RYsat% = set y axis rotation saturation
  • Return Value: na
Sets the y axis rotation value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_RZ_SATURATION(joynum%, RZsat% )
  • joynum% = game device number
  • RZsat% = set z axis rotation saturation
  • Return Value: na
Sets the z axis rotation value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| JOY_SLIDER_SATURATION(joynum%, num%, Slider_sat% )
  • joynum% = game device number
  • num% = specify slider number 0-1
  • Slider_sat% = set slider saturation
  • Return Value: na
Sets the slider value for the saturation zones of the game device in the range from 0 through 10000. The saturation level is the point at which the axis is considered to be at its most extreme position. For example, if the saturation level is set to 9500, the axis reaches the extreme of its range when it has moved 95 percent of the physical distance from its center position (or from the dead zone).


^| CREATE_EFFECT%()
  • [no params]
  • Return Value: Effect Handle
Call this command when you want to start creating force feedback effects of your own. This command basically creates a template for you to then use the SET_EFFECT_* commands to design the effect with. Also, everytime you create an effect with this command an internal value increments by 1 and returns it as an Effect Handle to be used with other commands. Each effect can be either of the four effect sytles:
CONSTANTFORCE, PERIODIC, RAMPFORCE or a CONDITION. You can set the style via there respective SET_EFFECT_* command. Also, you can ever further manipulate the style effects (except for the CONDITION style) by creating an envelope using the CREATE_ENVELOPE command. Finally, you will want to assign this effect to a game device by using the ATTACH_EFFECT command.


^| SET_EFFECT_AXES(effectnum%,axestype%,directiontype%,dir0%,dir1%)
  • effectnum% = Effect Handle
  • axestype% = 0 - X axis only, 1 - Y axis only, 2 - Both X & Y axis
  • directiontype% = 0 - Polar, 1 - Cartesian
  • dir0% = x direction value depending on directiontype
  • dir1% = y direction value depending on directiontype
  • Return Value: na
Call this command to allow the effect to effect the specified axis via polar or cartesian directions.

Using a Polar direction type, the direction values are expressed as a single angle, in hundredths of a degree clockwise from whatever zero-point, or true north, has been established for the effect. Normally this is the negative y-axis; that is, away from the user. Thus an effect with a polar coordinate of 9000 normally has a direction of east, or to the user's right, and the user must exert force to the right to counteract it.

Cartesian direction values are similar to 3-D vectors. If you draw a straight line on graph paper with an origin of (0, 0) at the center of the page, the direction of the line can be defined by the coordinates of any intersection that it crosses, regardless of the distance from the origin. A direction of (1, –2) and a direction of (5, –10) are exactly the same.


^| SET_EFFECT_DURATION(effectnum%,duration%,bINFINITE%)
  • effectnum% = Effect Handle
  • duration% = duration of the effect, in microseconds.
  • bINFINITE% = boolean value to set INFINITE duration on or off.
  • Return Value: na
If bINFINITE% is set to true( ie: on ), the effect has infinite duration. If an envelope has been applied to the effect, the attack is applied, followed by an infinite sustain.


^| SET_EFFECT_SAMPLEPERIOD(effectnum%,SamplePeriod%)
  • effectnum% = Effect Handle
  • SamplePeriod% = The period at which the game device should play back the effect, in microseconds.
  • Return Value: na
A SamplePeriod% value of 0 indicates that the default playback sample rate should be used. If the device is not capable of playing back the effect at the specified rate, it chooses the supported rate that is closest to the requested value. Setting the SamplePeriod% can be used for special effects. For example, playing a sine wave at an artificially large sample period results in a rougher texture.


^| SET_EFFECT_GAIN(effectnum%,Gain%)
  • effectnum% = Effect Handle
  • Gain% = range from 0 through 10000.
  • Return Value: na
The gain is a scaling factor applied to all magnitudes of the effect and its envelope. The higher the gain value, the more you "feel" from the effect( ie: it's like the volume for sound ).


^| SET_EFFECT_CONSTANTFORCE(EffectNum%,EnvNum%,Magnitude%)
  • EffectNum% = Effect Handle
  • EnvNum% = Envelope Handle
  • Magnitude% = range from –10000 through 10000
  • Return Value: na
Call this command if you want a steady force in a single direction. Setting the magnitude value sets the strength of the force. A negative magnitude value sets it in an oppsite direction. If an envelope is applied to this effect, the magnitude value represents the magnitude of the sustain. If no envelope is applied, the magnitude value represents the amplitude of the entire effect.


^| SET_EFFECT_PERIODIC(EffectNum%,EffectType%,EnvNum%,Magnitude%,Offset%,Phase%,Period%)
  • EffectNum% = Effect Handle
  • EffectType% = Type of periodic effect to use( 0 - 4 )
  • EnvNum% = Envelope Handle
  • Magnitude% = range from –10000 through 10000
  • Offset% =
  • Phase% =
  • Period% =
  • Return Value: na
Call this command to set the effect as a Periodic effect. Periodic effects are waveform effects.
Effect Type:
0 = Square
1 = Sine
2 = Triangle
3 = SawtoothUp
4 = SawtoothDown

Magnitude is the force at the peak of the wave.
Periodic effects can be modified by the offset, which defines the amount by which the waveform is shifted up or down from the base level. The practical effect of applying a positive offset to the sawtooth example would be to strengthen the positive force and weaken the negative one—in other words, the force would peak more strongly in one direction than in the other. The absolute value of the offset plus the magnitude of the effect must not exceed 10000.
The phase of a periodic effect is the point along the waveform where the effect begins. Phase is measured in hundredths of a degree, from 0 to 35,999. A game device driver can round off a phase value to the nearest supported value. For example, for a sine effect some drivers support only values in the range from 0 through 9,000 (to create a cosine); for other effects, only values in the range from 0 through 18,000 are supported.
Do not confuse the period of a periodic effect with the sample period ( ie:
SET_EFFECT_SAMPLEPERIOD). The period is the length of time that it takes to go through a complete wave cycle. The sample period, as for all effects, is the minimum time between actual adjustments of magnitude.


^| SET_EFFECT_RAMPFORCE(EffectNum%,EnvNum%,RampStart%,RampEnd%)
  • EffectNum% = Effect Handle
  • EnvNum% = Envelope Handle
  • RampStart% =
  • RampEnd% =
  • Return Value: na
Call this command to set the effect as a ramp force effect. A ramp force is a force with defined starting and ending magnitudes and a finite duration. A ramp force can continue in a single direction, or it can start as a strong push in one direction, weaken, stop, and then strengthen in the opposite direction.
DirectInput advises never to set duration to INFINITE ( ie: via the
SET_EFFECT_DURATIONcommand ) with a ramp force effect.


^| SET_EFFECT_CONDITION(EffectNum%,EffectType%,Offset%,PositiveCoefficient%,NegativeCoefficient%,PositiveSaturation%,NegativeSaturation%,DeadBand%)
[Command under construction!]

  • EffectNum% = Effect Handle
  • EffectType% = Type of condition effect to use( 0 - 3 )
  • Offset% = range from –10000 through 10000
  • PositiveCoefficient% = Coefficient constant on the positive side of the offset, in the range from –10000 through 10000.
  • NegativeCoefficient% = Coefficient constant on the negative side of the offset, in the range from –10000 through 10000.
  • PositiveSaturation% = Maximum force output on the positive side of the offset, in the range from 0 through 10000.
  • NegativeSaturation% = Maximum force output on the negative side of the offset, in the range from 0 through 10000.
  • DeadBand% = Region around Offset in which the condition is not active, in the range from 0 through 10000. In other words, the condition is not active between Offset minus DeadBand and Offset plus DeadBand.
  • Return Value: na
Call this command when you need a force that occurs only in response to input by the user. Two examples are a friction effect that generates resistance to movement of the joystick, and a spring effect that tends to move the stick back to a certain position after it has been moved from that position.
Effect Type:
0 = Spring
1 = Damper
2 = Inertia
3 = Friction

The offset from the 0 reading of the appropriate sensor value at which the condition begins to be applied. For a spring effect, the neutral point, that is the point along the axis at which the spring would be considered at rest, would be defined by the offset for the condition. For a damper, the offset would define the greatest velocity value for which damping force is 0. Offset is not normally used for inertia or friction effects.
BETA, TEMP TEXT - Will be updated when command is finalized...
Coefficient
A multiplier that scales the effect. For some devices, you can set separate coefficients for the positive and negative direction along the axis associated with the condition. For example, a flight stick controlling a damaged aircraft might move more easily to the right than to the left.

Saturation
In force feedback, saturation is an expression of the maximum possible force for an effect. For example, suppose a flight stick has a spring condition on the x-axis. The offset is 0, and the coefficient is 10,000, so the maximum force is normally exerted when the stick is furthest from the center. But if you define a positive and negative saturation of 5,000, the force does not increase after the stick has been moved halfway to the right or left. Not all devices support saturation.

Deadband
The deadband is a zone around the offset of an axis at which the condition is not active. In the case of a spring that is at rest in the middle of an axis, the deadband enlarges this area of rest. Not all devices support saturation.

Conditions can have duration, although in most cases, you would probably want to set the duration to infinite (–1) and stop the effect only in response to some event in the application.

The type-specific structure for conditions is DICONDITION. For multiple-axis conditions, you can provide an array of such structures, one for each axis, or a single structure that defines the condition in the specified direction. In either case, you must set the cbTypeSpecificParams member of the DIEFFECT structure to the number of bytes used; that is, to sizeof(DICONDITION) * n, where n is the number of structures provided. For more information on how to use either single or multiple structures, see the Remarks for the DICONDITION structure.

An application should call the IDirectInputDevice7::GetEffectInfo method or the IDirectInputDevice7::EnumEffects method and examine the dwEffectType member of the DIEFFECTINFO structure to determine whether both a positive and a negative coefficient and saturation for the effect are supported on the device. If the effect does not return the DIEFT_POSNEGCOEFFICIENTS flag, it ignores the value in the lNegativeCoefficient member, and the value in lPositiveCoefficient is applied to the entire axis. Likewise, if the effect does not return the DIEFT_POSNEGSATURATION flag, it ignores the value in dwNegativeSaturation, and the value in dwPositiveSaturation is used as the negative saturation level. Finally, if the effect does not return the DIEFT_SATURATION flag, it ignores both the dwPositiveSaturation and dwNegativeSaturation values, and no saturation is applied.

You can set a coefficient to a negative value, and this has the effect of generating the force in the opposite direction. For example, for a spring effect, it would cause the spring to push away from the offset point, rather than pulling toward it.

You should also check DIEFFECTINFO.dwEffectType for the DIEFT_DEADBAND flag, to see if deadband is supported for the condition. If it is not supported, the value in the lDeadBand member of the DICONDITION structure is ignored.

Different types of conditions interpret the parameters differently, but the basic idea is that force resulting from a condition is equal to A(q - q0) where A is a scaling coefficient, q is some metric, and q0 is the neutral value for that metric.

The preceding simplified formula must be adjusted if a nonzero dead band is provided. If the metric is less than lOffset - lDeadBand, the resulting force is given by the following formula:

force = lNegativeCoefficient * (q - (lOffset - lDeadBand))

Similarly, if the metric is greater than lOffset + lDeadBand, the resulting force is given by the following formula:

force = lPositiveCoefficient * (q - (lOffset + lDeadBand))

A spring condition uses axis position as the metric.

A damper condition uses axis velocity as the metric.

An inertia condition uses axis acceleration as the metric.

If the number of DICONDITION structures in the array is equal to the number of axes for the effect, the first structure applies to the first axis, the second applies to the second axis, and so on. For example, a two-axis spring condition with lOffset set to 0 in both DICONDITION structures would have the same effect as the joystick self-centering spring. When a condition is defined for each axis in this way, the effect must not be rotated.

If there is a single DICONDITION structure for an effect with more than one axis, the direction along which the parameters of the DICONDITION structure are in effect is determined by the direction parameters passed in the rglDirection field of the DIEFFECT structure. For example, a friction condition rotated 45 degrees (in polar coordinates) would resist joystick motion in the northeast-southwest direction but would have no effect on joystick motion in the northwest-southeast direction.




^| CREATE_ENVELOPE%(AttackLevel%,AttackTime%,FadeLevel%,FadeTime%)
  • AttackLevel% = Amplitude for the start of the envelope, relative to the baseline, in the range from 0 through 10000.
  • AttackTime% = The time, in microseconds, to reach the sustain level.
  • FadeLevel% = Amplitude for the end of the envelope, relative to the baseline, in the range from 0 through 10000.
  • FadeTime% = The time, in microseconds, to reach the fade level.
  • Return Value: Envelope Handle
Call this command when you want to modify/shape the basic magnitude of effects by applying an envelope and an offset. An envelope defines an attack value and a fade value, which modify the beginning and ending magnitude of the effect. Attack and fade also have duration, which determines how long the magnitude takes to reach or fall away from the sustain value, the magnitude in the middle portion of the effect.

To apply an envelope when creating or modifying an effect, set the returned Envelope Handle to the EnvNum% parameter of the effect sytle your working with (ie:
CONSTANTFORCE, PERIODIC or RAMPFORCE command. The CONDITION command does not support envelopes.

To determine whether a particular effect supports an envelope, call the IDirectInputDevice7::GetEffectInfo method, and check for the DIEP_ENVELOPE flag in the dwStaticParams member of the DIEFFECTINFO structure.

To apply an offset, set the lOffset member of the DIPERIODIC or the DICONDITION structure pointed to by the lpvTypeSpecificParams member of the DIEFFECT structure. For periodic effects, the absolute value of the offset plus the magnitude of the effect must not exceed DI_FFNOMINALMAX.

You cannot apply an offset to a constant force or ramp force. In these cases, the same effect can be achieved by altering the magnitude.


^| ATTACH_EFFECT%(JoyNum%,EffectNum%)
  • JoyNum% = Game Device Handle
  • EffectNum% = Effect Handle
  • Return Value: 1 = Successful, 0 = Failed
Call this command when you want to apply a created effect to the game device.


^| PLAY_EFFECT%(EffectNum%)
  • EffectNum% = Effect Handle
  • Return Value: 1 = Successful, 0 = Failed
Call this command when you want to play the effect. (ie: Play the effect on a button press from your game device, play the effect when your player runs against a wall or even if you player is envolved in an explosion, etc...)


^| STOP_EFFECT%(EffectNum%)
  • EffectNum% = Effect Handle
  • Return Value: 1 = Successful, 0 = Failed
Call this command to simply stop the effect from playing. Very useful when you are playing an infinite playing effect.


^| UNATTACH_EFFECT%(EffectNum%)
  • EffectNum% = Effect Handle
  • Return Value: 1 = Successful, 0 = Failed
Call this command when you want to take the effect out of the game devices' buffer. ie: make room for another effect to play. Note that you can NOT load as many effects into a game device as you want! all game devices has some kind of buffer limit to hold them.


^| CLEAR_EFFECT(EffectNum%)
  • EffectNum% = Effect Handle
  • Return Value:
Call this command on the effect to zero out it's values when you want to change the effect during realtime. Clear the effect, recreate only the parts of the effect that you want changed, and then call the
UPDATE_EFFECT command on it to finally change the effect during realtime.


^| UPDATE_EFFECT%(EffectNum%,bRestart%,bAxes%,bDirection%,bDuration%,bEnvelope%,bGain%,bSampleperiod%,bStartDelay%)
  • EffectNum% = Effect Handle
  • bRestart% = set to true to stop effect load effect and the play it. Set to false for on the fly updating.
  • bAxes% = True to updating axis
  • bDirection% = True to update direction
  • bDuration% = True to update duration
  • bEnvelope% = True to update envelope
  • bGain% = True to update gain
  • bSampleperiod% = True to update sampleperiod
  • bStartDelay% = True to update startdelay
  • Return Value: 1 = Successful, 0 = Failed
Call this command to finally update and change the effect during realtime. You need to set the boolean parameters in respect to what changes in the effect you want updatedd!


^| HAS_DYNAMIC_EFFECT_SUPPORT%(JoyNum%,EffectNum%,SupportType%)
  • JoyNum% = Game Device Handle
  • EffectNum% = Effect Handle
  • SupportType% = A support type effect ranging from 0-6
  • Return Value:
Call this cammand to see what effect type that can be modified while the effect is playing.
Support Type:
0 - AXES
1 - DIRECTION
2 - DURATION
3 - ENVELOPE
4 - GAIN
5 - SAMPLEPERIOD
6 - STARTDELAY

Note: If your application attempts to change an effect type while the effect is playing and the driver does not support modifying that effect dynamically, the driver is permitted to stop the effect, update it, then restart it.


^| HAS_EFFECT_SUPPORT%(JoyNum%,EffectNum%,SupportType%)
  • JoyNum% = Game Device Handle
  • EffectNum% = Effect Handle
  • SupportType% = A support type effect ranging from 0-6
  • Return Value:
Call this cammand to see what effects are supported by the effect.
Support Type:
0 - AXES
1 - DIRECTION
2 - DURATION
3 - ENVELOPE
4 - GAIN
5 - SAMPLEPERIOD
6 - STARTDELAY




Todo(no pacticular order):
- Decide how to implement SET_EFFECT_CONDITION correctly.
- Add a SET_EFFECT_SPHERICAL_AXES command.... do i need to??? well??? it uses x,y and z axis. is it for VR gadgets???
- Somehow add a "game device is full of effects" command.
- Add a SET_EFFECT_CUSTOM command.
- Add Write Effect to File command.
- Add Load_FFB_Effect command.
- Fix bugs that you all find.
- Add Examples that you all create.
- More dll debug info...
- Somehow, dunno how, but somehow , find a way to add more info and just make it the docs better all around... help?

History:
1) May 20,2007:
- First Beta Release - Let's see how it goes...