Using and creating a window can use issues in game capture if multiple
game captures are active, so revert back to using a mutex, and just
ignore the keepalive check failure if injected inside a UWP program
(only check to see if GetLastError reports that it's not found -- if it
returns access denied or any other error, assume it's in a UWP program,
and ignore the keepalive check).
If the backbuffer count is larger than 3, it could still try to assign
backbuffers to pointers beyond the variable's array size when calling
swap->GetBuffer.
D3D12 capture does not take in to account when multiple backbuffers are
in used. With previous versions of Direct3D there was no need to do
this, but with D3D12 you must explicitly capture each specific
backbuffer currently in use.
All named objects (including file mapped shared memory) need to be
created within the hook itself due to the fact that UWP programs cannot
access named objects outside of the UWP process.
Because shared memory needs to be created within the hook, the capture
loop cannot start until the shared memory has been filled with valid
data. Creating an additional "initialize" event fixes this issue.
Additionally, changed the way that named kernel objects are
opened/created. Before, there were functions that would first try to
open named objects and then implicitly create them if opening failed
(assuming that if the hook didn't create it first, game capture would),
now it's been changed so that you can only either explicitly open or
create.
To check to make sure game capture is still active in the capture
program, it currently uses a named event, and then it checks to see if
that named event exists. However with UWP programs, you can't open a
named event outside of the UWP process. FindWindow on the other hand
does work, so instead of checking to see if a named kernel object
exists, create a window and check to see if that window exists.
Instead of calling OpenThread, use DuplicateHandle with the minimal
access rights (SYNCHRONIZE) to be able to get the current thread handle
within a UWP program.
This prevents issues with using standard C functions, where microsoft
would otherwise spit out pointless warnings to encourage using
microsoft-specific functions instead.
(Note: This commit also modifies the ipc-util/seg-service modules)
When compiling the final project, always compile
ipc-util/get-graphics-offsets/graphics-hook/inject-helper/seg-service
with static MSVC runtimes to prevent the need of requiring the MSVC
runtimes for both architectures.
It's supposed to look for patch segments in ascending order, from the
smallest offset to the largest offset. Patch type/comparison is
identical to the one it's being swapped with, so only the offsets need
to be swapped.
This reverts commit 4c505e7030.
Reverting this for the time being due to issues with quakelive. This
will be more thoroughly tested and hopefully added again.
Tested using FTL (steam): SwapBuffers ultimately calls wgl_swap_buffers
causing an additional copy which just isn't necessary
This also causes game capture to sometimes capture overlays even when
not intended
Removing this union fixes the internal compile error that would occur on
visual studio 2015 update 2 and above when these variables were all in a
union.
Fixes a bug where if a D3D9 program recreates its device the capture
would become invalid. Certain games (especially blizzard games) will
completely recreate their Direct3D device if a critical D3D9 error
occurs.
Darkest dungeon uses an unusual technique for drawing its frames: a
fixed 1920x1080 frame buffer used in place of the backbuffer, which is
then stretched to fit the size of the screen (whether the screen is
bigger or smaller than the actual texture).
The custom frame would cause glReadBuffer to initially fail with an
error. When this happens, their custom frame buffer is in use, so all
that needs to be done is simply reset the capture and force the current
output size to 1920x1080 while that custom frame is in use.
They presumably did this in order to ensure the game looks the same at
any resolution. Instead of having to use power-of-two sprites and
mipmaps for every single game sprite and stretch/skew each of them
(which would risk the final output "not looking quite right" at
different resolutions), they simply use non-pow-2 sprites with no
mipmaps and render them all on to one texture of a fixed size and then
stretch that final output texture. That ensures that the actual
composite of the game still looks the same at any resolution, while
reducing texture memory by not requiring each sprite to use a
power-of-two texture and mipmaps.
Some games don't catch GL errors via glGetError, so there's a
possibility that an error will pass through to the capture calls,
causing a false failure.
The most simple solution is to just clear the error flag on each capture
call.
The virtual address table values for Reset/ResetEx can sometimes point
to functions that are in libraries outside of D3D8.dll and D3D9.dll, and
will cause a crash if used. Instead, just hook Reset/ResetEx when one
of the Present* functions are called.
Instead of using shell functions to get the windows system directory,
use the kernel32 functions (GetSystemDirectory and
GetSystemWow64Directory). Reduces a bit of unnecessary overhead.
If the GL capture part of the game capture hook fails to initialized for
whatever reason, it will go in to an infinite reacquire loop. If it
fails to initialize shared texture capture, try shared memory capture
instead.
..This is rather embarrassing. I used the parameter variable and the
actual variable that I wanted to used went completely unused. Would
static analysis catch something like this, I wonder? Would probably
have to be really good static analysis.
I had this issue where IDXGISwapChain::ResizeBuffers would fail in the
hooks, causing games to crash when they resized their backbuffers
because ResizeBuffers would return an 'invalid call' HRESULT value. In
the ResizeBuffers documentation it says that it will only happen if a
backbuffer currently has any outstanding references, but there's no way
this would happen unless ResizeBuffers internally calls Present or vise
versa.
After ResizeBuffers has been called, the very first call to Present will
somehow seemingly invalidate and/or destroy the current backbuffer.
It's very strange, but that seems to be what's going on, at least for
the game I was testing. So if you are performing a post-overlay
capture, then you must ignore the capture on the very first call to
Present.
It's Microsoft's code so you can't really know what's going on, you just
have to work around these strange issues seemingly in the dark.
Apparently someone dumb (aka me) neglected to properly handle the inline
graphics hook API functions. You're not supposed to 'extern' inline
functions, they need to be defined for each file when ever they're used.
Apparently neglected to use the reference operator. I think this may
partially be one of the reasons why many developers still choose to use
pointers instead of references, but fortunately an actual GOOD compiler
warns about this (aka anything but vc)