Jump to content

Thrustmaster Combined Full DX Mapping (extending the 32 DX buttons limit)


Recommended Posts

OK there seems to be a pretty major issue...

The buttons on the virtual joystick don't synchronise to the real buttons when you run the script, so all directx buttons stay off until you move the switch they are driven by.

 

So you have to toggle EVERY switch, EVERY time you run the script to get the output buttons to be properly synchronised.

 

I found a kind of dodgy way to synchronise them all at once, but you still need to cause a single update by pressing any button/moving any axis.

 

Add this at the end of the main function:

 

// Update all the throttle inputs to synchronise the mapped outputs with the actual device state

// Not needed for the joystick as all buttons are momentary

int i=0;

while(i < 52) {

DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);

i = i + 1;

}

 

Do you know of any way to trigger an update so it will work without any manual actions at all?

 

 

I never tested. If you want something to be done ONCE at profile loading, you need to put it within the "main()" function, preferably after the call to Init() (or DXpInit()) function. The EventHandle() function is a callback, called EACH TIME (and only if) new data is received from the device (button press/release, axis move, etc.)

 

 

 

I think the better way to avoid this problem is to map all switches with "PULSE", like:

 

 

MapKey(&Throttle, BSB, PULSE+DX51);
MapKey(&Throttle, BSM, PULSE+DX52);
MapKey(&Throttle, BSF, PULSE+DX53);

Link to comment
Share on other sites

I was hoping you guys could answer a question. I have read Thrustmasters PDF on using the script editor. The first thing that confuses me is that when you want to open a new file your presented with three options .tmc, .tmh, and .ttm but no where in the PDF does it tell you what the different files are for and what they do.

 

At first I thought the tmc file was a master file that called (included) all the tmh files that were needed to create the profile, but I see from MAIN.tmc that the only "included" files are hid.tmh and defines.tmh. That blows my first assumption out of the water.

 

My next issue is in the very first post in this thread. It leads me to believe that you could change one number (32 to 120) and add the define lines for DX33 through DX120 and it would work. So why create a whole other file? I.E. targetdx128.tmh.

 

Could you possibly provide a working set of files and a short explanation of how they interact with each other?

MSI Z490 Tomahawk, I5-11600kf, 2X512GB NvME, RTX4090, 32GB DDR4 3200, Reverb G2, T50-CM2, OpenXR

31st TFW, 14th MAS, 9th ARS

Link to comment
Share on other sites

I never tested. If you want something to be done ONCE at profile loading, you need to put it within the "main()" function, preferably after the call to Init() (or DXpInit()) function. The EventHandle() function is a callback, called EACH TIME (and only if) new data is received from the device (button press/release, axis move, etc.)

 

I think the better way to avoid this problem is to map all switches with "PULSE"

 

Sorry I don't think I was clear enough on the issue. Maybe it doesn't happen to you?

But for me, the new DX buttons don't get set until I move the associated switch.

 

Eg on the throttle a 3 position switch has positions UP/MID/DN, which are mapped to 3 DX buttons DX1/DX2/DX3.

There should always be one of those DX buttons active, no matter what position the switch is in.

But when running the TARGET script, all 3 DX outputs are 0, so in DCS the switches are in the default state and not the same as the real switch.

The DCS option of "synchronise to HOTAS on mission start" is on, but the DX buttons are all zero so it has no effect.

 

The switch has to be moved eg to UP and the state will change to 1/0/0 then back to mid -> 0/1/0 for the state to be synchronised.

PULSE mode will not help, as the initial state of the switches will still not be synchronised.

 

For me, I had to move EVERY mapped switch to get the correct synchronised outputs. Does this not happen to you?

The code I added at the end of main improves this so any switch or axis change will synchronise all buttons at once, but still one manual action is needed.

Link to comment
Share on other sites

I was hoping you guys could answer a question. I have read Thrustmasters PDF on using the script editor. The first thing that confuses me is that when you want to open a new file your presented with three options .tmc, .tmh, and .ttm but no where in the PDF does it tell you what the different files are for and what they do.

 

I have a total of 1 day of experience in this, and the documentation is terrible, but it seems .tmc and .tmh are basically equivalent to .c and .h files in C programming.

That is, .ttc is the main script file to be compiled and .tth are header files that provide definitions and functions for the .ttc.

.ttm are some kind of macro file, not sure how they are used.

 

My next issue is in the very first post in this thread. It leads me to believe that you could change one number (32 to 120) and add the define lines for DX33 through DX120 and it would work. So why create a whole other file? I.E. targetdx128.tmh.

 

Just enabling more virtual buttons wouldn't really do anything useful by itself.

The files by sedenion map all of the buttons and switches so that each switch state has a separate directX button which can be used in DCS.

 

For example, the 2 position switches on the throttle eg EAC only give one output that is either on or off.

So in the DCS F/A-18 if you want to use it for gear up/down you can't properly (without .lua editing). If you map it to "gear down" then it will put the gear down, but switching it the other way does nothing because there is no opposite signal to map to "gear up".

Sedenion's script gives you the required 2 directX outputs so you can map it properly: one when the button is up and another when it is down.

 

Similarly, 3-position switches give 3 outputs instead of just being off in the centre position.

There are also extra functions to increase the number of buttons, it is commented well so easy to understand.

 

Could you possibly provide a working set of files and a short explanation of how they interact with each other?

 

The files you want are in this post: https://forums.eagle.ru/showpost.php?p=4016316&postcount=41

Get the TM Warthog Universal HID.zip one, there's a readme and plenty of comments in the files.

The main.tmc is the script that does all the mappings, the .tmh files in the include directory define constants and functions to make the main code clean and understandable.

 

Add my code in post 50 if the buttons don't synchronise properly...

Link to comment
Share on other sites

For me, I had to move EVERY mapped switch to get the correct synchronised outputs. Does this not happen to you?

The code I added at the end of main improves this so any switch or axis change will synchronise all buttons at once, but still one manual action is needed.

 

 

I understand, but this never anoyed me this way. You maybe can found some helpfull code to adapt in my sws.tmh file in the "TM Warthog DX++" profile. The module is not used, but the code work. I used it a while to do this synchronisation when specific button is pressed. This may work by putting the commands in the "main()" function instead by calling it via conditionnals and events withing the event callback.

Link to comment
Share on other sites

I understand, but this never anoyed me this way. You maybe can found some helpfull code to adapt in my sws.tmh file in the "TM Warthog DX++" profile. The module is not used, but the code work. I used it a while to do this synchronisation when specific button is pressed. This may work by putting the commands in the "main()" function instead by calling it via conditionnals and events withing the event callback.

 

Thanks, your SyncVirtualBtn function does the same thing as the code I added to the end of main.

I still couldn't find a way to trigger an update of the outputs without having to press a button or move an axis, but that's not much trouble so I'm satisfied with how it is working.

Link to comment
Share on other sites

Thanks, your SyncVirtualBtn function does the same thing as the code I added to the end of main.

I still couldn't find a way to trigger an update of the outputs without having to press a button or move an axis, but that's not much trouble so I'm satisfied with how it is working.

 

 

I made some tests with the Device Analyzer, then review my own C/C++ implementation of HID game device handling, then all becam clear: The Microsoft HID API does not allow to get the current device state until driver send an input data chunk (which do contain the device state), and driver send input data chunk only on physical device state changes (and according some filters to prevent data flood)...

 

So, when you start any software (Device Analyzer or DCS, or whathever), the initial device state is defined by the software (neutral or 0 axis with all buttons released in most cases), and the device state is updated only when you change the device's physical state, forcing the driver to send an input data chunk to all softwares listening to HID events...

 

In two words: It is not a bug, it is a Microsoft API limitation, what you want to be done, cannot be done, even at C API level... Complains to Microsoft's dev team :D


Edited by sedenion
Link to comment
Share on other sites

I made some tests with the Device Analyzer, then review my own C/C++ implementation of HID game device handling, then all becam clear: The Microsoft HID API does not allow to get the current device state until driver send an input data chunk (which do contain the device state), and driver send input data chunk only on physical device state changes (and according some filters to prevent data flood)...

 

So, when you start any software (Device Analyzer or DCS, or whathever), the initial device state is defined by the software (neutral or 0 axis with all buttons released in most cases), and the device state is updated only when you change the device's physical state, forcing the driver to send an input data chunk to all softwares listening to HID events...

 

In two words: It is not a bug, it is a Microsoft API limitation, what you want to be done, cannot be done, even at C API level... Complains to Microsoft's dev team :D

 

Hehe thanks for investigating, I thought it was a limitation in TARGET but it being Microsoft's fault is somehow not surprising! :doh:

Link to comment
Share on other sites

  • 3 weeks later...
OK there seems to be a pretty major issue...

The buttons on the virtual joystick don't synchronise to the real buttons when you run the script, so all directx buttons stay off until you move the switch they are driven by.

 

So you have to toggle EVERY switch, EVERY time you run the script to get the output buttons to be properly synchronised.

 

I found a kind of dodgy way to synchronise them all at once, but you still need to cause a single update by pressing any button/moving any axis.

 

Add this at the end of the main function:

 

// Update all the throttle inputs to synchronise the mapped outputs with the actual device state

// Not needed for the joystick as all buttons are momentary

int i=0;

while(i < 52) {

DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);

i = i + 1;

}

 

Do you know of any way to trigger an update so it will work without any manual actions at all?

 

 

In what place in my script should I paste this, please?

The synchronization issue is very important to me too!

 

My script attached

FA-18 Throttle.zip

Окурок, выброшенный в урну, гораздо патриотичнее флажочка на автомобиле

TM Wartrhog Stick + VPC MongoosT-50Base + VPC TMW Extension 150mm / TM Wartrhog Throttle / CH Pro Pedals / 2-VPC Deck Mount / TrackIR5/

__________________________________________________________

i5-10600K Over to 5.0MHz/32GbDD4-3200/RTX4070/System-SSD1 DCS-SSD2/32" 2560x1440

Link to comment
Share on other sites

In what place in my script should I paste this, please?

The synchronization issue is very important to me too!

 

My script attached

 

 

At the end of the main() function, just before ce closing brace '}' :

 

 

int main() 
{ 

 // your mapping commands...

 int i=0;
 while(i < 52) {
   DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);
   i = i + 1;
 }
}



Link to comment
Share on other sites

At the end of the main() function, just before ce closing brace '}' :

 

 

int main() 
{ 

 // your mapping commands...

 int i=0;
 while(i < 52) {
   DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);
   i = i + 1;
 }
}



I added here, saved, but when I start my DCS profile (or edit profile) through TARGET - all changes in script are deleted !! :huh:

 

..........................................................................................

MapAxis(&Throttle, THR_LEFT, DX_ZROT_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);

SetSCurve(&Throttle, THR_LEFT, 0, 0, 0, 0, 0);

MapAxis(&Throttle, THR_FC, DX_SLIDER_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);

SetSCurve(&Throttle, THR_FC, 0, 0, 0, 0, 0);

int i=0;

while(i < 52) {

DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);

i = i + 1;

}

int EventHandle(int type, alias o, int x)

{

DefaultMapping(&o, x);

}


Edited by SMN

Окурок, выброшенный в урну, гораздо патриотичнее флажочка на автомобиле

TM Wartrhog Stick + VPC MongoosT-50Base + VPC TMW Extension 150mm / TM Wartrhog Throttle / CH Pro Pedals / 2-VPC Deck Mount / TrackIR5/

__________________________________________________________

i5-10600K Over to 5.0MHz/32GbDD4-3200/RTX4070/System-SSD1 DCS-SSD2/32" 2560x1440

Link to comment
Share on other sites

MapAxis(&Throttle, THR_LEFT, DX_ZROT_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
    SetSCurve(&Throttle, THR_LEFT, 0, 0, 0, 0, 0);
   MapAxis(&Throttle, THR_FC, DX_SLIDER_AXIS, AXIS_NORMAL, MAP_ABSOLUTE);
   SetSCurve(&Throttle, THR_FC, 0, 0, 0, 0, 0);
 int i=0;
 while(i < 52) {
   DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);
   i = i + 1;
}
int EventHandle(int type, alias o, int x)
{
   DefaultMapping(&o, x);
}

 

 

Your code cannot copile, you forgot a closing braces. Pay attention, every time you see an opening brace '{' it must be a closing one '}' corresponding...

 

In your case, you forgot to close the main() or while()... you must add a closing brace, like that:

 

 

[color=Navy]int[/color] main()
[b][color=Red]{[/color][/b] [color=Gray][i]//<   main() function opening brace[/i][/color]

   [color=Gray]// mapping commands here[/color]

   [color=navy]int[/color] i=0;
   [color=navy]while[/color](i < 52) [b][color=Red]{[/color] [/b][color=gray][i]//<   while() loop opening brace[/i][/color]
        DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);
        i = i + 1;
[b][color=Red]    }[/color] [/b][color=gray][i]//<   while() lopp closing brace[/i][/color]

[color=red][b]}[/b][/color] [color=gray]//<   main() function closing brace[/color]

[color=navy]int[/color] EventHandle(int type, alias o, int x)
[b][color=red]{[/color][/b]
      DefaultMapping(&o, x);
[b][color=red]}[/color][/b]


Edited by sedenion
Link to comment
Share on other sites

Your code cannot copile, you forgot a closing braces. Pay attention, every time you see an opening brace '{' it must be a closing one '}' corresponding...

 

In your case, you forgot to close the main() or while()... you must add a closing brace, like that:

 

 

[color=Navy]int[/color] main()
[b][color=Red]{[/color][/b] [color=Gray][i]//<   main() function opening brace[/i][/color]

    [color=Gray]// mapping commands here[/color]
[color=Gray]
[/color]

   [color=navy]int[/color] i=0;
   [color=navy]while[/color](i < 52) [b][color=Red]{[/color] [/b][color=gray][i]//<   while() loop opening brace[/i][/color]
        DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);
        i = i + 1;
[b][color=Red]    }[/color] [/b][color=gray][i]//<   while() lopp closing brace[/i][/color]

[color=red][b]}[/b][/color] [color=gray]//<   main() function closing brace[/color]

[color=navy]int[/color] EventHandle(int type, alias o, int x)
[b][color=red]{[/color][/b]
      DefaultMapping(&o, x);
[b][color=red]}[/color][/b]

 

 

Ok. I made this. Same - all changes in script are deleted

 

int main() { //< main() function opening brace // mapping commands here

int i=0;

while(i < 52) {

DefEventHandler(EV_HID_INPUT_DATA, &Throttle, i);

i = i + 1;

}

}

int EventHandle(int type, alias o, int x)

{

DefaultMapping(&o, x);

}

Окурок, выброшенный в урну, гораздо патриотичнее флажочка на автомобиле

TM Wartrhog Stick + VPC MongoosT-50Base + VPC TMW Extension 150mm / TM Wartrhog Throttle / CH Pro Pedals / 2-VPC Deck Mount / TrackIR5/

__________________________________________________________

i5-10600K Over to 5.0MHz/32GbDD4-3200/RTX4070/System-SSD1 DCS-SSD2/32" 2560x1440

Link to comment
Share on other sites

What do you mean "all changes in scripts are deleted" ? I don't understand...

Deleted from script...

 

See video...

Окурок, выброшенный в урну, гораздо патриотичнее флажочка на автомобиле

TM Wartrhog Stick + VPC MongoosT-50Base + VPC TMW Extension 150mm / TM Wartrhog Throttle / CH Pro Pedals / 2-VPC Deck Mount / TrackIR5/

__________________________________________________________

i5-10600K Over to 5.0MHz/32GbDD4-3200/RTX4070/System-SSD1 DCS-SSD2/32" 2560x1440

Link to comment
Share on other sites

Do not use Target GUI, it is not suitable for advanced scripting, you have to edit and run the script from Target Script Editor. If you try to edit an advanced script using Target GUI, it will always rewrite le script using default minimalistic pattern.

 

 

Oops ... I get it!

Thanks!:thumbup:

Окурок, выброшенный в урну, гораздо патриотичнее флажочка на автомобиле

TM Wartrhog Stick + VPC MongoosT-50Base + VPC TMW Extension 150mm / TM Wartrhog Throttle / CH Pro Pedals / 2-VPC Deck Mount / TrackIR5/

__________________________________________________________

i5-10600K Over to 5.0MHz/32GbDD4-3200/RTX4070/System-SSD1 DCS-SSD2/32" 2560x1440

Link to comment
Share on other sites

  • 6 months later...

I used the DX button mod (dx+.tmh) and made a target profile, which creates joystick + keyboard and maps all joystick + throttle buttons to DX buttons. Then I added a some magic and created shift layer+tempo combinations that use the same DX buttons and adds CTL+SHF modifiers depending on the layer and short/long presses.

 

I tought I would be able to map buttons and the modified buttons to DCS without creating too many separate DX buttons.

 

In addition to the DX buttons I send keyboard keys for Track IR + Cocpit Views with long presses / shift layer.

 

All worked well until I added the layer + modifier combinations to all hats plus few other buttons. Now I'm getting an error when running the script and pressing a modified button: Runtime Error: Index out of bounds for: h2blookup in _key ( line 557 in target.tmh )

 

I know there's a 120 button limit, but I'm obviously pushing the script over some other boundary too. Am I trying to be too clever and should I just create more DX buttons and use those instead of using combinations of modifiers?

 

Edit: This turned out to be use error > I had input wrong constants for modifiers. I accidentally used virtual keycodes from defines.h instead of the actual modifier constants which are defined in target.tmh.


Edited by pjl
Problem solved!
Link to comment
Share on other sites

  • 3 weeks later...

Hey all, I know this thread is old, but trying to get this script to work for my Warthog throttle and ran into this error message...seems to not like my rudder pedals? Can anyone help me out with what I might need to do to make the throttle script work? Thanks much!

 

Mapped plugin module "C:\Program Files (x86)\Thrustmaster\TARGET\Plugins\sys.dll"

Physical USB HID devices managed by script!

Currently plugged USB HID devices[3]:

1: "Joystick - HOTAS Warthog" - "USB\VID_044F&PID_0402&REV_0100"

2: "Throttle - HOTAS Warthog" - "USB\VID_044F&PID_0404&REV_0100"

3: "T-Rudder" - "USB\VID_044F&PID_B679&REV_0110"

Installing filter driver to VID_044F&PID_0404. Please Wait...Script stopped!

Done!

Error: (internal) cannot associate a filter with the selected USB HID device "VID_044F&PID_0404"

 

Runtime Error: STOP request received while running main on line 12 in "C:\Program Files (x86)\Thrustmaster\TARGET\scripts\WarthogThrottleALLSwitchPos.tmc"

Error: Script run timed out!

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

Actually, looking at it now, it looks like it might be some problem with the throttle...weird. I'm running the latest version of TARGET and firmware is updated.

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

Well, got the script running successfully after making the registry corrections for the devices. All is well in the device analyzer, but when I go into DCS to assign the new DX positions for the toggles, DCS does not recognize the new switches, meaning, only the up position of the EAC switch works, and is identifed as DV24, rather than DX41 or whatever it is when the script is running.

 

I feel like I've almost got this thing...what am I missing to get DCS to recognize the new DX buttons that TARGET is recognizing?

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

Man...TARGET is FUN!

 

So, I've copied the main, dx+, pov and ldc files into the scripts folder, but when I try to compile or run, I get this:

 

Loaded plugin module "C:\Program Files (x86)\Thrustmaster\TARGET\Plugins\sys.dll"(*)

Compiling script: main.tmc

Compile Error:File not found: include/dx+.tmh in main.tmc at line 71

 

What the hell? The file is IN THE COMPUTER. What am I missing guys. BTW, I had the original file working, but switched to the new Warthog Universal in hopes it would make DCS recognize the new DX buttons...but now I can't get the script to run. Totally confused.

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

Okay, figured out those includes had to be in a separate folder in the scripts directory. Script now compiles, but trying to figure out where exactly to add the little bit of initializing code to avoid having to throw every single switch to make it work...

 

...or do I not have to do that? Having actually tried it in DCS yet...let's do that.

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

ARRGH! Okay, I have GOT to be missing a step. All the buttons are working correctly in device analyzer, but when I go into DCS and try to map, say the RDR ALTM switch, it still only works in the up position, tripping JOY_BTN25, instead of the newly scripted DX67.

 

What step am I missing here? Is there more configuring that I have to do in TARGET to assign all the new DX buttons to the hardware? How do I use the controls page in DCS to map my newly scripted DX buttons? DCS is still just seeing the default 32 DX button mapping on the throttle and stick.

 

I appreciate any help...it's got to be something I'm just missing.

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

Also, can someone help me understand how to make the DMS switch just four more DX buttons, rather than the POV, as I use TrackIR? Really appreciate the assist, thank you.

[sIGPIC][/sIGPIC]

Website:https://cvw-8.enjin.com/

Discord:https://discord.gg/b8AgE5m

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...