From c3b15e25d664022be473170d3f41934ed93af787 Mon Sep 17 00:00:00 2001 From: somewhatlurker <52014015+somewhatlurker@users.noreply.github.com> Date: Wed, 25 Sep 2019 01:32:25 +1000 Subject: [PATCH] add a maybe-working version of DivaMovie lol --- source-code/PD-Loader.sln | 8 + .../plugins/DivaMovie/DivaMovie.vcxproj | 92 ++++++++++ .../DivaMovie/DivaMovie.vcxproj.filters | 9 + .../source/plugins/DivaMovie/dllmain.cpp | 170 ++++++++++++++++++ .../source/plugins/DivaMovie/framework.h | 62 +++++++ 5 files changed, 341 insertions(+) create mode 100644 source-code/source/plugins/DivaMovie/DivaMovie.vcxproj create mode 100644 source-code/source/plugins/DivaMovie/DivaMovie.vcxproj.filters create mode 100644 source-code/source/plugins/DivaMovie/dllmain.cpp create mode 100644 source-code/source/plugins/DivaMovie/framework.h diff --git a/source-code/PD-Loader.sln b/source-code/PD-Loader.sln index e6e5059..ee6d287 100644 --- a/source-code/PD-Loader.sln +++ b/source-code/PD-Loader.sln @@ -17,6 +17,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fakedll", "source\fakedll\f EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaSound", "source\plugins\DivaSound\DivaSound.vcxproj", "{EE1A551A-49A0-40F2-8C2E-862D0AE55B43}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaMovie", "source\plugins\DivaMovie\DivaMovie.vcxproj", "{1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -79,6 +81,12 @@ Global {EE1A551A-49A0-40F2-8C2E-862D0AE55B43}.Release|x64.ActiveCfg = Release|x64 {EE1A551A-49A0-40F2-8C2E-862D0AE55B43}.Release|x64.Build.0 = Release|x64 {EE1A551A-49A0-40F2-8C2E-862D0AE55B43}.Release|x86.ActiveCfg = Release|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x64.ActiveCfg = Debug|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x64.Build.0 = Debug|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x86.ActiveCfg = Debug|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.ActiveCfg = Release|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.Build.0 = Release|x64 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x86.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj b/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj new file mode 100644 index 0000000..35db075 --- /dev/null +++ b/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj @@ -0,0 +1,92 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {1994C586-F73B-4EF2-BA3E-2A0FC3034B1A} + DivaMovie + 10.0 + + + + DynamicLibrary + true + v142 + MultiByte + + + DynamicLibrary + false + v142 + true + MultiByte + + + + + + + + + + + + + + + .dva + + + .dva + + + + Level3 + Disabled + true + true + ..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories) + + + Console + ..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories) + detours.lib;evr.lib;mfplat.lib;mfuuid.lib;strmiids.lib;syelog.lib;%(AdditionalDependencies) + + + + + Level3 + MaxSpeed + true + true + true + true + ..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories) + + + Console + true + true + detours.lib;evr.lib;mfplat.lib;mfuuid.lib;syelog.lib;%(AdditionalDependencies) + ..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + \ No newline at end of file diff --git a/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj.filters b/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj.filters new file mode 100644 index 0000000..d746774 --- /dev/null +++ b/source-code/source/plugins/DivaMovie/DivaMovie.vcxproj.filters @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/source-code/source/plugins/DivaMovie/dllmain.cpp b/source-code/source/plugins/DivaMovie/dllmain.cpp new file mode 100644 index 0000000..ccfa5f9 --- /dev/null +++ b/source-code/source/plugins/DivaMovie/dllmain.cpp @@ -0,0 +1,170 @@ +#include "framework.h" + +#include + +#include +#include +#include + +#include +#include +#include + +IDirect3DDeviceManager9* deviceManager; + +IMFTransform* mfTransform; +int width; +int height; +unsigned long samplesize; +unsigned long subtype; + +IMFSample* dstSample; +IDirect3DSurface9* dstSurface; +IMFSample* srcSample; +IMFMediaBuffer* srcBuffer; + +HRESULT initialize(IMFTransform* transform) +{ + HRESULT result = S_OK; + + IMFMediaType* type = NULL; + IMFMediaBuffer* buffer = NULL; + HANDLE hDevice = NULL; + IDirectXVideoAccelerationService* service = NULL; + + AM_MEDIA_TYPE* format = NULL; + VIDEOINFOHEADER2* header = NULL; + + // Release what we already had beforehand + SAFE_RELEASE(mfTransform); + SAFE_RELEASE(dstSample); + SAFE_RELEASE(dstSurface); + SAFE_RELEASE(srcSample); + SAFE_RELEASE(srcBuffer); + + ASSERT(transform->GetOutputCurrentType(0, &type)); + ASSERT(type->GetRepresentation(AM_MEDIA_TYPE_REPRESENTATION, (void**)&format)); + + header = (VIDEOINFOHEADER2*)format->pbFormat; + + width = header->bmiHeader.biWidth; + height = header->bmiHeader.biHeight; + samplesize = format->lSampleSize; + subtype = format->subtype.Data1; + + // System memory sample + ASSERT(MFCreateSample(&srcSample)); + ASSERT(MFCreateMemoryBuffer(format->lSampleSize, &buffer)); + ASSERT(srcSample->AddBuffer(buffer)); + ASSERT(buffer->QueryInterface(&srcBuffer)); + + // Video memory sample + ASSERT(deviceManager->OpenDeviceHandle(&hDevice)); + ASSERT(deviceManager->GetVideoService(hDevice, __uuidof(IDirectXVideoAccelerationService), (void**)& service)); + ASSERT(service->CreateSurface(width, height, 0, (D3DFORMAT)subtype, D3DPOOL_DEFAULT, 0, DXVA2_VideoSoftwareRenderTarget, &dstSurface, NULL)); + ASSERT(MFCreateVideoSampleFromSurface(dstSurface, &dstSample)); + ASSERT(deviceManager->CloseDeviceHandle(hDevice)); + + mfTransform = transform; + mfTransform->AddRef(); + +end: + if (format) + type->FreeRepresentation(AM_MEDIA_TYPE_REPRESENTATION, format); + + SAFE_RELEASE(service); + SAFE_RELEASE(buffer); + SAFE_RELEASE(type); + + return result; +} + +VTABLE_HOOK(HRESULT, IMFTransform, ProcessOutput, DWORD dwFlags, DWORD cOutputBufferCount, + MFT_OUTPUT_DATA_BUFFER* pOutputSamples, DWORD* pdwStatus) +{ + if (pOutputSamples->pSample != NULL || deviceManager == NULL || cOutputBufferCount != 1) + return originalProcessOutput(This, dwFlags, cOutputBufferCount, pOutputSamples, pdwStatus); + + HRESULT result = S_OK; + + if (mfTransform != This) + ASSERT(initialize(This)); + + pOutputSamples->pSample = srcSample; + pOutputSamples->pSample->AddRef(); + + ASSERT(originalProcessOutput(This, dwFlags, cOutputBufferCount, pOutputSamples, pdwStatus)); + + D3DLOCKED_RECT rect; + BYTE* buf; + ASSERT(srcBuffer->Lock(&buf, NULL, NULL)); + ASSERT(dstSurface->LockRect(&rect, NULL, NULL)); + ASSERT(MFCopyImage((BYTE*)rect.pBits, rect.Pitch, buf, samplesize, samplesize, 1)); + ASSERT(dstSurface->UnlockRect()); + ASSERT(srcBuffer->Unlock()); + + LONGLONG duration; + ASSERT(srcSample->GetSampleDuration(&duration)); + ASSERT(dstSample->SetSampleDuration(duration)); + + LONGLONG time; + ASSERT(srcSample->GetSampleTime(&time)); + ASSERT(dstSample->SetSampleTime(time)); + + DWORD flags; + ASSERT(srcSample->GetSampleFlags(&flags)); + ASSERT(dstSample->SetSampleFlags(flags)); + + pOutputSamples->pSample->Release(); + pOutputSamples->pSample = dstSample; + pOutputSamples->pSample->AddRef(); +end: + return result; +} + +VTABLE_HOOK(HRESULT, IMFTransform, ProcessMessage, MFT_MESSAGE_TYPE eMessage, ULONG_PTR ulParam) +{ + HRESULT result = originalProcessMessage(This, eMessage, ulParam); + if (eMessage == MFT_MESSAGE_SET_D3D_MANAGER && result == MF_E_UNSUPPORTED_D3D_TYPE) + { + result = originalProcessMessage(This, eMessage, NULL); + if (SUCCEEDED(result)) + INSTALL_VTABLE_HOOK(This, ProcessOutput, 25); + } + return result; +} + +HOOK(void*, IMFTransformInitializer, 0x140420B90, void* a1, void* a2, IMFTransform** transform) +{ + void* result = originalIMFTransformInitializer(a1, a2, transform); + INSTALL_VTABLE_HOOK(*transform, ProcessMessage, 23); + return result; +} + +HOOK(HRESULT, DXVA2CreateDirect3DDeviceManager, PROC_ADDRESS("dxva2.dll", "DXVA2CreateDirect3DDeviceManager9"), + UINT* pResetToken, IDirect3DDeviceManager9** ppDeviceManager) +{ + HRESULT result = originalDXVA2CreateDirect3DDeviceManager(pResetToken, ppDeviceManager); + + if (FAILED(result)) + return result; + + if (deviceManager) + deviceManager->Release(); + + deviceManager = *ppDeviceManager; + deviceManager->AddRef(); + + return result; +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + INSTALL_HOOK(DXVA2CreateDirect3DDeviceManager); + INSTALL_HOOK(IMFTransformInitializer); + } + + return TRUE; +} \ No newline at end of file diff --git a/source-code/source/plugins/DivaMovie/framework.h b/source-code/source/plugins/DivaMovie/framework.h new file mode 100644 index 0000000..08002d0 --- /dev/null +++ b/source-code/source/plugins/DivaMovie/framework.h @@ -0,0 +1,62 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include + +#if _DEBUG +#define PRINT(value, ...) printf(value, __VA_ARGS__); +#else +#define PRINT(value, ...) +#endif + +#define PROC_ADDRESS(libraryName, procName) \ + GetProcAddress(LoadLibrary(TEXT(libraryName)), procName) + +#define SAFE_RELEASE(object) if (object) { object->Release(); object = NULL; } + +#define VTABLE_HOOK(returnType, className, functionName, ...) \ + typedef returnType functionName(className* This, __VA_ARGS__); \ + functionName* original##functionName; \ + returnType implOf##functionName(className* This, __VA_ARGS__) + +#define INSTALL_VTABLE_HOOK(object, functionName, functionIndex) \ + { \ + void** addr = &(*(void***)object)[functionIndex]; \ + if (*addr != implOf##functionName) \ + { \ + PRINT("[DivaMovie] Installing %s hook...\n", #functionName); \ + original##functionName = (functionName*)*addr; \ + DWORD oldProtect; \ + VirtualProtect(addr, sizeof(void*), PAGE_EXECUTE_READWRITE, &oldProtect); \ + *addr = implOf##functionName; \ + VirtualProtect(addr, sizeof(void*), oldProtect, NULL); \ + } \ + } + +#define HOOK(returnType, function, location, ...) \ + typedef returnType function(__VA_ARGS__); \ + function* original##function = (function*)location; \ + returnType implOf##function(__VA_ARGS__) + +#define INSTALL_HOOK(functionName) \ + { \ + PRINT("[DivaMovie] Installing %s hook...\n", #functionName); \ + DetourTransactionBegin(); \ + DetourUpdateThread(GetCurrentThread()); \ + DetourAttach((void**)&original##functionName, implOf##functionName); \ + DetourTransactionCommit(); \ + } + +#define ASSERT(function) \ + if (FAILED(result = (function))) \ + { \ + PRINT("[DivaMovie] %s failed (error code: 0x%08x)\n", #function, (unsigned int)result); \ + goto end; \ + } \ + else \ + { \ + PRINT("[DivaMovie] %s succeeded\n", #function); \ + } \ No newline at end of file