win-capture: Add trick to ensure game cap. shared tex support
This new trick forgoes the use of patches and allows the ability to use shared GPU resources despite being a Direct3D 9.0c context.
This commit is contained in:
@@ -80,17 +80,107 @@ static inline void d3d9_free(d3d9_info &info)
|
||||
DestroyWindow(info.hwnd);
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
|
||||
#define CMP_SIZE 21
|
||||
|
||||
static const uint8_t mask[CMP_SIZE] =
|
||||
{0xF8, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0x00,
|
||||
0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static const uint8_t mask_cmp[CMP_SIZE] =
|
||||
{0x48, 0x8B, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x39, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0x00,
|
||||
0x40, 0xB8, 0x00, 0x00, 0x00, 0x00};
|
||||
#else
|
||||
|
||||
#define CMP_SIZE 19
|
||||
|
||||
static const uint8_t mask[CMP_SIZE] =
|
||||
{0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0x00,
|
||||
0xFF, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
static const uint8_t mask_cmp[CMP_SIZE] =
|
||||
{0x8B, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x39, 0x80, 0x00, 0x00, 0x00, 0x00,
|
||||
0x75, 0x00,
|
||||
0x68, 0x00, 0x00, 0x00, 0x00};
|
||||
#endif
|
||||
|
||||
#define MAX_FUNC_SCAN_BYTES 200
|
||||
|
||||
static inline bool pattern_matches(uint8_t *byte)
|
||||
{
|
||||
for (size_t i = 0; i < CMP_SIZE; i++) {
|
||||
if ((byte[i] & mask[i]) != mask_cmp[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void get_d3d9_offsets(struct d3d9_offsets *offsets)
|
||||
{
|
||||
d3d9_info info = {};
|
||||
bool success = d3d9_init(info);
|
||||
|
||||
if (success) {
|
||||
uint8_t **vt = *(uint8_t***)info.device;
|
||||
uint8_t *crr = vt[125];
|
||||
|
||||
offsets->present = vtable_offset(info.module, info.device, 17);
|
||||
offsets->present_ex = vtable_offset(info.module, info.device,
|
||||
121);
|
||||
offsets->present_swap = vtable_offset(info.module, info.swap,
|
||||
3);
|
||||
|
||||
for (size_t i = 0; i < MAX_FUNC_SCAN_BYTES; i++) {
|
||||
if (pattern_matches(&crr[i])) {
|
||||
#define get_offset(x) *(uint32_t*)&crr[i + x]
|
||||
#ifdef _WIN64
|
||||
uint32_t off1 = get_offset(3);
|
||||
uint32_t off2 = get_offset(9);
|
||||
#else
|
||||
uint32_t off1 = get_offset(2);
|
||||
uint32_t off2 = get_offset(8);
|
||||
#endif
|
||||
|
||||
/* check to make sure offsets are within
|
||||
* expected values */
|
||||
if (off1 > 0xFFFF || off2 > 0xFFFF)
|
||||
break;
|
||||
|
||||
/* check to make sure offsets actually point
|
||||
* toward expected data */
|
||||
#ifdef _MSC_VER
|
||||
__try {
|
||||
uint8_t *ptr = (uint8_t*)(info.device);
|
||||
|
||||
uint8_t *d3d9_ptr =
|
||||
*(uint8_t**)(ptr + off1);
|
||||
if (d3d9_ptr != (uint8_t*)info.d3d9ex)
|
||||
break;
|
||||
|
||||
BOOL &is_d3d9ex =
|
||||
*(BOOL*)(d3d9_ptr + off2);
|
||||
if (is_d3d9ex != TRUE)
|
||||
break;
|
||||
|
||||
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
offsets->d3d9_clsoff = off1;
|
||||
offsets->is_d3d9ex_clsoff = off2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d3d9_free(info);
|
||||
|
@@ -31,6 +31,8 @@ int main(int argc, char *argv[])
|
||||
printf("present=0x%"PRIx32"\n", d3d9.present);
|
||||
printf("present_ex=0x%"PRIx32"\n", d3d9.present_ex);
|
||||
printf("present_swap=0x%"PRIx32"\n", d3d9.present_swap);
|
||||
printf("d3d9_clsoff=0x%"PRIx32"\n", d3d9.d3d9_clsoff);
|
||||
printf("is_d3d9ex_clsoff=0x%"PRIx32"\n", d3d9.is_d3d9ex_clsoff);
|
||||
printf("[dxgi]\n");
|
||||
printf("present=0x%"PRIx32"\n", dxgi.present);
|
||||
printf("resize=0x%"PRIx32"\n", dxgi.resize);
|
||||
|
Reference in New Issue
Block a user