elishacloud / dxwrapper

Fixes compatibility issues with older games running on Windows 10/11 by wrapping DirectX dlls. Also allows loading custom libraries with the file extension .asi into game processes.
zlib License
1.15k stars 82 forks source link

Texture not using SetTexture? #200

Closed dkollmann closed 1 year ago

dkollmann commented 1 year ago

Hello guys, I am now at the point where I have to make some game specific hacks. For this I detect textures and assign a "special role" to them.

Replacing the texture is already working... image

however, I would rather like to skip the geometry alltogether.

So my idea was to store the "special role" of the current texture, but I cannot find it.

HRESULT m_IDirect3DDeviceX::SetTexture(...)
...
m_IDirect3DTextureX *pTextureX = nullptr;
lpTexture->QueryInterface(IID_GetInterfaceX, (LPVOID*)&pTextureX);
...
CurrentTextureSpecialRole = pSurfaceX->GetSpecialRole();

if(CurrentTextureSpecialRole == SurfaceSpecialRole::HandDecal)
{
    LOG_LIMIT(100, __FUNCTION__);  // never triggers
}

Any suggestions? Thank you

elishacloud commented 1 year ago

For this I detect textures and assign a "special role" to them.

How are you detecting the texture to assign it a role?

  1. Are you sure that the correct SurfaceX is getting the role and that the surface is one that is actually used in a SetTexture() call? Try logging the address of the SurfaceX that you assign the role to and then logging all the SetTexture() calls to see the game ever calls SetTexture on that surface.
  2. Are you using the correct SetTexture() function? From the code above it looks like the wrong one. There are two SetTexture functions. This game only calls the one that looks like this: HRESULT m_IDirect3DDeviceX::SetTexture(DWORD dwStage, LPDIRECTDRAWSURFACE7 lpSurface)
dkollmann commented 1 year ago

The role is correctly assigned, which the texture replacement already uses.

I cannot see any SetTexture for that surface. Here is what the log lists for the surface 1A2AA0F0.

It is a dynamic texture, the shadow of the hand, that is why I need to prevent the game from locking it, otherwise it would be replaced again.

3636 20:01:39.461 m_IDirectDrawSurfaceX::IsLost (1A2AA0F0)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirectDrawSurfaceX::Lock2 (1A2AA0F0)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirectDrawSurfaceX::LockD39Surface (1A2AA0F0) prevent lock of hand decal!
3636 20:01:39.461 m_IDirectDrawSurfaceX::LockD39Surface (1A2AA0F0) prevent lock of hand decal!
3636 20:01:39.461 m_IDirectDrawSurfaceX::Lock2 Error: failed to lock surface texture. is Texture Size: 32x32 Format: D3DFMT_A4R4G4B4 dwCaps: 0x10405008 IsLocked: 0 IsInDC: 0
3636 20:01:39.461 m_IDirectDrawSurfaceX::Unlock (1A2AA0F0)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirect3DTexture9::UnlockRect (1A2D0E68)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirectDrawSurfaceX::Blt (092DA7A0)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirect3DDevice9Ex::TestCooperativeLevel (09220420)
3636 20:01:39.461 m_IDirectDrawSurfaceX::QueryInterface (1A2AA0F0) IID_GetInterfaceX
dkollmann commented 1 year ago

Okay I found it. It is handled through blitting.

HRESULT m_IDirectDrawSurfaceX::Blt(LPRECT lpDestRect, LPDIRECTDRAWSURFACE7 lpDDSrcSurface, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx, bool isSkipScene)
{
...
// Get source surface
m_IDirectDrawSurfaceX* lpDDSrcSurfaceX = (m_IDirectDrawSurfaceX*)lpDDSrcSurface;
if (!lpDDSrcSurfaceX)
{
    lpDDSrcSurfaceX = this;
}
else
{
    lpDDSrcSurfaceX->QueryInterface(IID_GetInterfaceX, (LPVOID*)&lpDDSrcSurfaceX);
}

// Handle special roles
if(lpDDSrcSurfaceX->SpecialRole == SurfaceSpecialRole::HandDecal)
{
    Logging::LogDebug() << __FUNCTION__ << " (" << this << ") skipped hand decal blitting!";
    hr = DDERR_GENERIC;
    break;
}
...
}
elishacloud commented 1 year ago

Okay I found it. It is handled through blitting.

LOL. Yeah, that is the other option I was going to say but left off for some reason. I wonder why the game author chose to blit the hand texture rather than just using SetTexture.

dkollmann commented 1 year ago

I am sure there was a good reason for it. In 1999. :p