Head Tracking Hook for XWA

A Forum dedicated to the Suggestion, Creation and Editing of XWA Dynamic Link Library Files

Moderator: JeremyaFr

Re: Head Tracking Hook for XWA

User avatar
JeremyaFr
XWAU Member
Posts: 3918
Joined: Mon Jan 18, 2010 5:52 pm
Contact:

Post by JeremyaFr » Sat Jun 01, 2019 4:49 pm

JeremyaFr wrote:
Sat Jun 01, 2019 4:31 pm
Both hooks hook the function at address 0x4F9A5F that retrieves the keyboard state.
One of the hook must be rewritten to avoid the conflict.
Instead of hooking the call to the function 0042B900, you can insert the call to the hook at the end of the function 0042B900 itself. There is 10 bytes free so it is enough to call a hook.

Justagai
Cadet 1st Class
Posts: 218
Joined: Mon Dec 08, 2014 10:59 pm

Post by Justagai » Sat Jun 01, 2019 7:02 pm

I attempted to hook at the end of 0042B900 but I was having some trouble. I decided to hook to at 0x4F9A61 instead and all is well with the two hooks. I apologize for the conflict of the hooks. I have sent the changes to blue_max.

User avatar
JeremyaFr
XWAU Member
Posts: 3918
Joined: Mon Jan 18, 2010 5:52 pm
Contact:

Post by JeremyaFr » Sat Jun 01, 2019 7:54 pm

It's fine.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Sun Jun 02, 2019 1:36 am

I'll remove the dependency with openvr_api.dll, that's not a problem. Also, Justagai just figured out how to avoid the conflict with the Windowed hook (it's basically what Jeremy said above).

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Tue Jun 04, 2019 5:53 am

Alright, here's version 0.9.2:

https://www.dropbox.com/s/h9w96fvl83kvq ... 2.zip?dl=0

I've applied the fix that Justagai sent me to avoid the conflict with Hook_Windowed.dll, this version has native support for TrackIR (thanks to ual002 and Ra'Kaan for their support in testing this) and OpenTrack; but I could not remove the dependency with openvr_api.dll. Sorry, it's too much of a hassle to do run-time linking against that DLL and I'd rather maintain a single version of this hook, so you'll still need the file there for the time being. If enough people are bothered by it, or if it needs to be removed for other reasons (maybe because someone may want to include this in the next XWAUP/DSUP release?) then I'll split the Hook into two versions.

Enjoy!

User avatar
ffaaway
Rebel Alliance
Posts: 92
Joined: Mon May 05, 2003 11:01 pm

Post by ffaaway » Tue Jun 04, 2019 6:35 am

I'll update the above posted install guide tomorrow with the new procedure without FreePIE and again when this reaches final release status. :)
X-Wing pilot since 1993 and still kickin'

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Tue Jun 04, 2019 5:48 pm

ffaaway wrote:
Tue Jun 04, 2019 6:35 am
I'll update the above posted install guide tomorrow with the new procedure without FreePIE and again when this reaches final release status. :)
Actually, it's probably better to leave that procedure because that still can be used as a fallback: if TrackIR does not work, people can still use the old method through FreePIE.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Sat Jun 08, 2019 6:02 am

Version 0.9.2 will crash in MultiPlayer; but Justagai figured out a way to fix the crash. However, the hook doesn't really work in MP due to synchronization issues: the camera just goes nuts and starts spinning around. Stil, I figured it's better than just crashing, so here's a new version that avoids the crash in MP mode:

https://www.dropbox.com/s/pah7iyp47q8f3 ... 3.zip?dl=0

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Sat Jun 08, 2019 6:08 am

Also, I've been testing a few ideas to enable Roll (so that one day we may have full 6dof in this game). The problem is that the game does not support roll natively (unless I'm mistaken here -- if someone can correct me and point me in the right direction I would certainly appreciate that!). So the only option that I see right now is to add the roll in ddraw. But here, the geometry has already been clipped and culled, so this is what a roll of 45 degrees looks like:
Roll-sample.jpg
That's what I mean when I say that it "doesn't look great". In VR, this may work because we can't see the edges of the screen when wearing the headset anyway; but I don't think people will ike to play like this with TrackIR.

I also tried increasing the scale of the starfield background to cover the edges of the screen... and again, it doesn't really work. It feels like you're swimming inside a sphere dotted with stars.
You do not have the required permissions to view the files attached to this post.

User avatar
Trevor
Lieutenant JG
Posts: 541
Joined: Thu Dec 04, 2014 7:11 pm

Post by Trevor » Sat Jun 08, 2019 4:34 pm

blue_max, why don't you use the same methods of the original VR where you are rendering your own 3d space? wouldn't this avoid the clip issue?

I know that in the original VR hook, the lateral movement still clipped, but it seemed more triangle based rather than view based?

Alternatively, why not just disable frustum clipping?

Also, as I mentioned in PM, Most VR games can be forced Out-Of-Bounds by players as the price for freedom, XWA should be no different. slight sways in your head can (and should) be represented on screen despite the clipping.

As I also stated, head tracking via mouselook has worked brilliantly, but you spoiled us with your key-mapped movements in your first hook and now I want it to return but mapped to head xyz instead :P

Trev

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Sat Jun 08, 2019 6:52 pm

Hey Trevor! This is the VR mod. It's the same problem.

Disabling the frustum clipping would fix this, yeah; but I don't know how to do that.

I can add the positional x,y,z back through the hook. It won't be perfect, as you know; but it's better than the roll and it feels right most of the time.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Jun 19, 2019 4:24 am

Minor update for this hook: the SteamVR mode crashes the game if it fails to initialize. I've fixed the crash and added a second attempt.

https://www.dropbox.com/s/pqn2bwe2vr83c ... 4.zip?dl=0

User avatar
Darksaber
Vice Admiral
Posts: 10931
Joined: Mon Jan 10, 2000 12:01 am
Contact:

Post by Darksaber » Wed Jun 19, 2019 6:39 am

Sorry but moving this to the XWA Hook Editing Forum
“You can please some of the people all of the time, you can please all of the people some of the time, but you can’t please all of the people all of the time”.”
- John Lydgate

Good Things Come To Those Who Wait....
Darksaber's X-Wing Station

User avatar
Driftwood
Admiral (Moderator)
Posts: 2174
Joined: Wed Oct 22, 2003 11:01 pm
Contact:

Post by Driftwood » Sat Jun 22, 2019 11:47 pm

Just got this working for my install, and I have to say it's fantastic.

It's going to take a while to get used to though, but it's a whole new dynamic to the game and it's literally throwing off my aim, but it's almost like playing ARMA or DCS sooo thank you!

I just wish there wasn't a need to run freePIE every time.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Jul 17, 2019 5:14 am

Driftwood wrote:
Sat Jun 22, 2019 11:47 pm
I just wish there wasn't a need to run freePIE every time.
Hey Driftwood, thanks for your comments. Sorry for the late response.

If you're talking about TrackIR, you shouldn't need to run FreePIE anymore. Are you running the latest version?

https://www.dropbox.com/s/pqn2bwe2vr83c ... 4.zip?dl=0

I can't test TrackIR directly; but others should be able to confirm that it works without FreePIE.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Jul 17, 2019 5:59 am

I just released a new version of this hook:

https://www.dropbox.com/s/3q0rbzebjjzwh ... 5.zip?dl=0

I added offsets to yaw and pitch and the ability to select the FreePIE slot to read from. The tracker can also be disabled by setting it to "None" to recover normal mouse look function without uninstalling it.

This version should be compatible with TrackIR directly, without FreePIE.

User avatar
ual002
XWAU Member
Posts: 983
Joined: Wed Sep 24, 2008 2:23 am

Post by ual002 » Wed Jul 17, 2019 1:32 pm

1. Out of curiosity, can anything be done to enable head tracking in the hangar?

2. Is there anyway we can keep the hangar view from automatically switching views on the player that wants to keep his head in the pit?
Image Image Image Image Image

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Jul 17, 2019 9:21 pm

I tried to enable head tracking in the hangar once and it didn't work. I'll check again, though. I don't know if it's possible to prevent the hangar from switching views, sorry. Maybe Justagai might now more in this area.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Sun Sep 29, 2019 5:23 am

Here's a new release of the cockpit look hook:

https://www.dropbox.com/s/da6aqizhfs02i ... 6.zip?dl=0

In this release:

* THE NAME OF THE HOOK HAS CHANGED to Hook_CockpitLook.dll. Please be aware that you'll have to remove the previous version of the hook or the game might crash on startup.
* I've re-enabled the keypad keys to look around the cockpit.
* The mouse can now be used to look around when the external camera is enabled.

User avatar
Darksaber
Vice Admiral
Posts: 10931
Joined: Mon Jan 10, 2000 12:01 am
Contact:

Post by Darksaber » Sun Sep 29, 2019 9:24 am

Thanks :)
“You can please some of the people all of the time, you can please all of the people some of the time, but you can’t please all of the people all of the time”.”
- John Lydgate

Good Things Come To Those Who Wait....
Darksaber's X-Wing Station

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Jan 15, 2020 2:25 am

Alright, here's version 1.0.0 with improved positional tracking to get 5dof support:

https://www.dropbox.com/s/f7sfpo6l8n2r7 ... 0.zip?dl=0

In this release, it's possible to move around the cockpit using the keyboard and stay in that position. So, for instance, it's possible to load the Falcon, move to Chewie's seat, and play from that position.

User avatar
blue_max
XWAU Member
Posts: 2293
Joined: Wed Mar 20, 2019 5:12 am

Post by blue_max » Wed Sep 16, 2020 5:18 am

Update: I just updated this hook to version 1.0.5. I applied some changes that were suggested by Jeremy to avoid conflicts with his joystick hook.

https://www.dropbox.com/s/3yvga6xz56m5q ... 5.zip?dl=0

User avatar
JeremyaFr
XWAU Member
Posts: 3918
Joined: Mon Jan 18, 2010 5:52 pm
Contact:

Post by JeremyaFr » Wed Sep 16, 2020 8:21 am

It works fine now.
Thank you :thumbs:

User avatar
m0rgg
XWAU Member
Posts: 266
Joined: Wed Apr 01, 2020 10:33 pm

Post by m0rgg » Wed Nov 03, 2021 3:57 pm

JeremyaFr wrote:
Sat Jun 01, 2019 4:49 pm
JeremyaFr wrote:
Sat Jun 01, 2019 4:31 pm
Both hooks hook the function at address 0x4F9A5F that retrieves the keyboard state.
One of the hook must be rewritten to avoid the conflict.
Instead of hooking the call to the function 0042B900, you can insert the call to the hook at the end of the function 0042B900 itself. There is 10 bytes free so it is enough to call a hook.
Justagai wrote:
Sat Jun 01, 2019 7:02 pm
I attempted to hook at the end of 0042B900 but I was having some trouble. I decided to hook to at 0x4F9A61 instead and all is well with the two hooks. I apologize for the conflict of the hooks. I have sent the changes to blue_max.
Hello,

I am trying to improve positional tracking by avoiding the use of the cockpit shake variables. If I just set the PlayerDataTable[].Camera.PositionX,Y,Z at the current hooked address, they get reset later inside PlayerCameraUpdate (0x4EE9F5).

Code: Select all

PlayerDataTable[playerIndex].Camera.PositionX = g_objectPtr[PlayerDataTable[playerIndex].Camera.CraftIndex].PosX;
    PlayerDataTable[playerIndex].Camera.PositionY = objPtr[PlayerDataTable[playerIndex].Camera.CraftIndex].PosY;
    PlayerDataTable[playerIndex].Camera.PositionZ = objPtr[PlayerDataTable[playerIndex].Camera.CraftIndex].PosZ;
    if ( PlayerDataTable[playerIndex].Camera.CraftIndex == PlayerDataTable[playerIndex].ObjectIndex )
    {
        UpdatePlayerMovement(playerIndexCount);
        PlayerDataTable[playerIndexCount].Camera.PositionX += (signed __int64)PlayerDataTable[playerIndexCount].CockpitPositionTranformed.x;
        PlayerDataTable[playerIndexCount].Camera.PositionY += (signed __int64)PlayerDataTable[playerIndexCount].CockpitPositionTranformed.y;
        v16 = (signed __int64)PlayerDataTable[playerIndexCount].CockpitPositionTranformed.z;
        objPtr = g_objectPtr;
        PlayerDataTable[playerIndex].Camera.PositionZ += v16;
    }
    PlayerDataTable[playerIndex].Camera.PositionX += PlayerDataTable[playerIndex].Camera.ShakeX >> 4;
    PlayerDataTable[playerIndex].Camera.PositionY += PlayerDataTable[playerIndex].Camera.ShakeY >> 4;
    PlayerDataTable[playerIndex].Camera.PositionZ += PlayerDataTable[playerIndex].Camera.ShakeZ >> 4;
I have also tried to offset the values of PlayerDataTable[].CockpitPositionTransformed without changing the current input hook (0x4F9A61), but it does not seem to work, I guess they get overwritten before the call to PlayerCameraUpdate.

To avoid this, ideally I would like to hook all calls to PlayerCameraUpdate and modify the camera values right before they are used, but I don't really know how to do that without breaking the behavior of the function.

The suggestion from @Random Starfighter was to hook one (or more) calls to the function instead, and call the original after running my code. This is the relevant code I added to hook the call inside DrawInFlightView (hopefully the latest before the rendering) at 0x4F2196.

Code: Select all

// cockpitlook.cpp
int PlayerCameraUpdateHook(int* params)
{
	char (*PlayerCameraUpdate)(int,int,int) = (char (*)(int,int,int))0x004EE820;
	log_debug("[DBG][CockpitLook] Running hooked PlayerCameraUpdate");

	return PlayerCameraUpdate(params[0],params[1],params[2]);
}

// hooks.h
static const HookFunction g_hookFunctions[] =
{
	{ 0x4F9A66, CockpitLookHook },
	{ 0x4F2196, PlayerCameraUpdateHook },
};

static const HookPatchItem g_patch[] =
{
	//////////////////// Hook Patches ////////////////////

	// Entry
	// First hook in PlayerInflightSystemInput to overwrite the mouselook values.
	{ 0xF8E61, "66399369A08B00", "E8BAF00A009090" },
	{ 0xF1596, "E885C6FFFF", "E8BAF00A00" },
[...]
But the additional g_patch item is currently making the game crash, even before my code is executed (it never reaches breakpoints set in CockpitLook code).
Exception thrown at 0x005A1265 in XwingAlliance.exe: 0xC0000005: Access violation reading location 0x0000003B.
I have also tried replacing by the value in the Hook_HelloWorld (E8E6B50800), but it also crashes, although the access violation is different.
Exception thrown at 0x0057D781 in XwingAlliance.exe: 0xC0000005: Access violation writing location 0x00000000.
I can try to understand the problem by debugging at those addresses but it will take a while, and I guess this must be a newbie mistake so I am asking for help here before going deeper in the rabbit hole.

Any suggestions @Justagai @JeremyaFr @Random Starfighter ?

Thanks in advance!

Random Starfighter
Cadet 3rd Class
Posts: 34
Joined: Tue Oct 13, 2020 12:14 am

Post by Random Starfighter » Wed Nov 03, 2021 11:35 pm

For the HookFunction entry, the address there needs to be the address of the return location, the beginning of next instruction.

Code: Select all

    004F2196 E8 85 C6 FF FF       call    PlayerCameraUpdate
--> 004F219B A0 94 C8 68 00       mov     al, byte_68C894
So your HookFunction entry should look like this.

Code: Select all

static const HookFunction g_hookFunctions[] =
{
    { 0x004F219B, PlayerCameraUpdateHook },
};
For the springboard part, the function is located at 0x005A8B20
So the calling instruction needs to be patched with the relative offset (again from the return address) to get there.

005A8B20 - 004F219B = B6985
Invert the byte order to 85 69 0B 00

Now your patch item should look like this. The result of 0xF1596 is fine instead of doing the subtraction by 0x400C00, I just like having addresses I can easily copy and paste to navigate around.

Code: Select all

static HookPatchItem g_HookPatches[] =
{
    { 0x004F2196 - 0x400C00, "E885C6FFFF", "E885690B00"},
};
One other thing, it looks like the PlayerCameraUpdate function only takes one argument. I'm not sure if it matters. But anyway here's the stub hook.

Code: Select all

int PlayerCameraUpdateHook(int *params)
{
    // Logging code, or whatever you want here.
    
    int(*PlayerCameraUpdate)(int) = (int(*)(int)) 0x004EE820;
    return PlayerCameraUpdate(params[0]);
}
Now your logging in PlayerCameraUpdateHook() should at least be functional, and you can go from there.

Post Reply