You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Trying to work with action event callbacks I was having problems with receiving seemingly nonsensical data in SteamInputActionEvent_t. using the pointer the callback gives you by investigating the actual byte data that I was receiving and reinterpreted manually I found the data was in fact being lost somewhere in translation
crude testing script
I was using godot so it uses godot to print to console. change GD.Print() to whatever you prefer for logging
protected SteamInputActionEventCallbackPointer actionCallback;
private void init()
{
actionCallback = OnActionEvent;
SteamInput.EnableActionEventCallbacks(actionCallback);
}
unsafe void OnActionEvent(IntPtr actionEvent)
{
SteamInputActionEvent_t actual = *(SteamInputActionEvent_t*)actionEvent;
SteamInputActionEvent_t coerced = coerceActionEventPointer(actionEvent);
GD.Print("Actual(correct) Hex ");
printActionEventHexData(&actual);
GD.Print("Coerced(incorrect) Hex");
printActionEventHexData(&coerced);
GD.Print("Actual Event(incorrect data interpretation)");
printActionEventData(actual);
GD.Print("Coerced Event(correct data interpretation)");
printActionEventData(coerced);
}
unsafe void printActionEventHexData(SteamInputActionEvent_t* actionEvent)
{
SteamInputActionEvent_t action = *actionEvent;
int size = 0;
switch (action.eEventType)
{
case ESteamInputActionEventType.ESteamInputActionEventType_DigitalAction:
size = 22;
break;
case ESteamInputActionEventType.ESteamInputActionEventType_AnalogAction:
size = 33;
break;
}
byte* bytes = (byte*)actionEvent;
StringBuilder build = new StringBuilder();
build.Append('[');
for (int i = 0; i < size; i++)
{
build.Append(Convert.ToHexString([bytes[i]]));
if (i is 7 or 11 or 19 || size == 22 & i == 20)
{
build.Append("] [");
}
else if (size == 33 && i is 23 or 27 or 31)
{
build.Append("] [");
}
else if (i == 32 || size == 22 && i == 21)
{
build.Append(']');
}
else
{
build.Append('-');
}
}
GD.Print(build.ToString());
}
unsafe SteamInputActionEvent_t coerceActionEventPointer(IntPtr actionEvent)
{
byte* ptr = (byte*)actionEvent;
InputHandle_t controller = new InputHandle_t(*(ulong*)ptr);
ESteamInputActionEventType eType = *(ESteamInputActionEventType*)(ptr + 8);
ulong* handle = (ulong*)(((byte*)ptr) + 12);
switch (eType)
{
case ESteamInputActionEventType.ESteamInputActionEventType_DigitalAction:
InputDigitalActionHandle_t digitalHandle = new InputDigitalActionHandle_t(handle[0]);
InputDigitalActionData_t digitalData = new InputDigitalActionData_t()
{
bState = ptr[20],
bActive = ptr[21]
};
return new SteamInputActionEvent_t()
{
controllerHandle = controller,
eEventType = eType,
m_val = new SteamInputActionEvent_t.OptionValue()
{
digitalAction = new SteamInputActionEvent_t.DigitalAction_t()
{
actionHandle = digitalHandle,
digitalActionData = digitalData
}
}
};
case ESteamInputActionEventType.ESteamInputActionEventType_AnalogAction:
InputAnalogActionHandle_t analogHandle = new InputAnalogActionHandle_t(handle[0]);
EInputSourceMode eMode = *(EInputSourceMode*)(ptr + 20);
float x = *(float*)(ptr + 24);
float y = *(float*)(ptr + 28);
byte bActive = ptr[32];
InputAnalogActionData_t analogData = new InputAnalogActionData_t()
{
eMode = eMode,
x = x,
y = y,
bActive = bActive
};
return new SteamInputActionEvent_t
{
controllerHandle = controller,
eEventType = eType,
m_val = new SteamInputActionEvent_t.OptionValue
{
analogAction = new SteamInputActionEvent_t.AnalogAction_t()
{
actionHandle = analogHandle,
analogActionData = analogData
}
}
};
}
throw new Exception("Etype not valid" + eType);
}
unsafe void printActionEventData(SteamInputActionEvent_t action)
{
StringBuilder builder = new StringBuilder();
builder.AppendLine("\tControllerHandle:" + action.controllerHandle);
builder.AppendLine("\tEventType:" + action.eEventType);
switch (action.eEventType)
{
case ESteamInputActionEventType.ESteamInputActionEventType_DigitalAction:
builder.AppendLine("\tDigitalActionHandle:" + action.m_val.digitalAction.actionHandle.m_InputDigitalActionHandle);
builder.AppendLine($"\tBState:{action.m_val.digitalAction.digitalActionData.bState} BActive: {action.m_val.digitalAction.digitalActionData.bActive}");
break;
case ESteamInputActionEventType.ESteamInputActionEventType_AnalogAction:
var actionData = action.m_val.analogAction.analogActionData;
builder.AppendLine("\tAnalogActionHandle: " + action.m_val.analogAction.actionHandle.m_InputAnalogActionHandle);
builder.AppendLine("\tEmode:" + actionData.eMode);
builder.AppendLine($"\tStickInput({actionData.x},{actionData.y})) BActive:{actionData.bActive}");
break;
}
GD.Print(builder);
}
Example Results
using the above functions I compared the actual data I received and the current interpretation with my manual interpretation and how the struct would translate my data and received these results: (values are separated based on native C++ layout) (data is in little-endian)
Coerced Event(correct data interpretation)
ControllerHandle:242343181104106
EventType:ESteamInputActionEventType_DigitalAction
DigitalActionHandle:2
BState:1 BActive: 1
Conclusions/Hypothesis
The problem lies with the OptionValue struct and how it organizes data. It looks like the C# struct is larger than the C++ native one as seen by the presumed cut-off float value from how I printed the data. It appears an extra 4 bytes are inserted before the bytes corresponding to the Digital/AnalogActionHandle_t. (in the coerced data bytes 13 - 16 (indexed at 1) should not be there)
As I write I'm realizing this is likely an issue of the enum ESteamInputActionEventType in C++ taking up 4 bytes as it is an int32 derived type while in C# it is derived from a 64 bit integer.
The text was updated successfully, but these errors were encountered:
brief description
Trying to work with action event callbacks I was having problems with receiving seemingly nonsensical data in SteamInputActionEvent_t. using the pointer the callback gives you by investigating the actual byte data that I was receiving and reinterpreted manually I found the data was in fact being lost somewhere in translation
crude testing script
I was using godot so it uses godot to print to console. change GD.Print() to whatever you prefer for logging
Example Results
using the above functions I compared the actual data I received and the current interpretation with my manual interpretation and how the struct would translate my data and received these results: (values are separated based on native C++ layout) (data is in little-endian)
Analog Example Output
Actual(correct) Hex
[EA-33-39-EB-68-DC-00-00] [01-00-00-00] [01-00-00-00-00-00-00-00] [06-00-00-00] [4C-29-A6-3E] [26-FD-92-BE] [01]
Coerced(incorrect) Hex
[EA-33-39-EB-68-DC-00-00] [01-00-00-00] [00-00-00-00-01-00-00-00] [00-00-00-00] [06-00-00-00] [4C-29-A6-3E] [26]
Actual Event(incorrect data interpretation)
ControllerHandle:242343181104106
EventType:ESteamInputActionEventType_AnalogAction
AnalogActionHandle: 25769803776
Emode:1051076940
StickInput(-0.28708762,1E-45)) BActive:0
Coerced Event(correct data interpretation)
ControllerHandle:242343181104106
EventType:ESteamInputActionEventType_AnalogAction
AnalogActionHandle: 1
Emode:k_EInputSourceMode_JoystickMove
StickInput(0.32453382,-0.28708762)) BActive:1
Digital Example Output
Actual(correct) Hex
[EA-33-39-EB-68-DC-00-00] [00-00-00-00] [02-00-00-00-00-00-00-00] [01] [01]
Coerced(incorrect) Hex
[EA-33-39-EB-68-DC-00-00] [00-00-00-00] [00-00-00-00-02-00-00-00] [00] [00]
Actual Event(incorrect data interpretation)
ControllerHandle:242343181104106
EventType:ESteamInputActionEventType_DigitalAction
DigitalActionHandle:1103806595072
BState:0 BActive: 0
Coerced Event(correct data interpretation)
ControllerHandle:242343181104106
EventType:ESteamInputActionEventType_DigitalAction
DigitalActionHandle:2
BState:1 BActive: 1
Conclusions/Hypothesis
The problem lies with the OptionValue struct and how it organizes data. It looks like the C# struct is larger than the C++ native one as seen by the presumed cut-off float value from how I printed the data. It appears an extra 4 bytes are inserted before the bytes corresponding to the Digital/AnalogActionHandle_t. (in the coerced data bytes 13 - 16 (indexed at 1) should not be there)As I write I'm realizing this is likely an issue of the enum ESteamInputActionEventType in C++ taking up 4 bytes as it is an int32 derived type while in C# it is derived from a 64 bit integer.
The text was updated successfully, but these errors were encountered: