add Novidia (non-Nvidia chara skinning)

This commit is contained in:
somewhatlurker
2020-07-22 16:28:46 +10:00
parent 243cbc3f94
commit 0bb614ce53
6 changed files with 482 additions and 0 deletions
+6
View File
@@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaWig", "source\plugins\D
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSCRemote", "source\plugins\DSCRemote\DSCRemote.vcxproj", "{8544C599-F73B-4EF2-BA3E-2A0FC3034B1A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Novidia", "source\plugins\Novidia\Novidia.vcxproj", "{47181A1D-C22C-4C9C-B4E0-CB6CE886A1D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -75,6 +77,10 @@ Global
{8544C599-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x64.Build.0 = Debug|x64
{8544C599-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.ActiveCfg = Release|x64
{8544C599-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.Build.0 = Release|x64
{47181A1D-C22C-4C9C-B4E0-CB6CE886A1D8}.Debug|x64.ActiveCfg = Debug|x64
{47181A1D-C22C-4C9C-B4E0-CB6CE886A1D8}.Debug|x64.Build.0 = Debug|x64
{47181A1D-C22C-4C9C-B4E0-CB6CE886A1D8}.Release|x64.ActiveCfg = Release|x64
{47181A1D-C22C-4C9C-B4E0-CB6CE886A1D8}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{47181a1d-c22c-4c9c-b4e0-cb6ce886a1d8}</ProjectGuid>
<RootNamespace>Novidia</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;detours.lib;syelog.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\dependencies\PluginConfigApi;..\..\..\dependencies\detours\include;</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>opengl32.lib;detours.lib;syelog.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\framework.h" />
<ClInclude Include="src\glStuff.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\glStuff.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -0,0 +1,163 @@
#include "framework.h"
#include "glStuff.h"
#include <PluginConfigApi.h>
// upload to the SSBO instead after processing
void h_uploadModelTransformBuf(DWORD* a1, int a2)
{
uploadModelTransformBuf(a1, a2);
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_1D, buf_tex);
//glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 0x3000 / sizeof(float) / 4, 0, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 0x3000 / sizeof(float) / 4, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
glActiveTexture(GL_TEXTURE0);
//glFinish();
}
/*
void h_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
{
if (performTransform)
{
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_1D, buf_tex);
//glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 0x3000 / sizeof(float) / 4, 0, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 0x3000 / sizeof(float) / 4, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
//glActiveTexture(GL_TEXTURE0);
}
glDrawElements(mode, count, type, indices);
}
void h_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
{
if (performTransform)
{
glActiveTexture(GL_TEXTURE8);
glBindTexture(GL_TEXTURE_1D, buf_tex);
//glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 0x3000 / sizeof(float) / 4, 0, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 0x3000 / sizeof(float) / 4, GL_RGBA, GL_FLOAT, *(float**)0x1411a3330);
//glActiveTexture(GL_TEXTURE0);
}
glDrawRangeElements(mode,start, end, count, type, indices);
}
*/
// just a crash fix
void h_glBindBuffer(GLenum target, GLuint buffer)
{
// if not okay, it's param buffer data
if (!checkBufferTargetOk(target))
{
return;
}
glBindBuffer(target, buffer);
}
// just a crash fix
void h_glBufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage)
{
// if not okay, it's param buffer data
if (!checkBufferTargetOk(target))
{
return;
}
glBufferData(target, size, data, usage);
}
PROC h_wglGetProcAddress(LPCSTR Arg1)
{
PROC res = wGlGetProcAddress_forhook(Arg1);
if (res == nullptr)
return (PROC)stub;
return res;
}
// used as an entry point after GL context is created
void h_glutSetCursor(int cursor)
{
if (!loadGlAddresses())
{
printf("[Novidia] Aborting loading\n");
//MessageBoxA(NULL, "!", NULL, NULL);
}
else
{
struct {
void* target;
void* hook;
} hookFuncs[] = {
{&glBindBuffer, h_glBindBuffer},
{&glBindBufferARB, h_glBindBuffer},
{&glBufferData, h_glBufferData},
{&glBufferDataARB, h_glBufferData},
//{&glDrawElements, h_glDrawElements},
//{&glDrawRangeElements, h_glDrawRangeElements},
};
for (auto fn : hookFuncs)
{
hookGlFunc((PROC*)fn.target, fn.hook);
}
//glActiveTexture(GL_TEXTURE8);
glGenTextures(1, &buf_tex);
glBindTexture(GL_TEXTURE_1D, buf_tex);
glTexStorage1D(GL_TEXTURE_1D, 1, GL_RGBA32F, 0x3000 / sizeof(float) / 4);
//glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, 0x3000 / sizeof(float) / 4, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
}
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
printf("[Novidia] Unhooking glutSetCursor\n");
DetourDetach(&(PVOID&)glutSetCursor, h_glutSetCursor);
DetourTransactionCommit();
glutSetCursor(cursor);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
//loadConfig();
DisableThreadLibraryCalls(hModule);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
printf("[Novidia] Hooking glutSetCursor\n");
DetourAttach(&(PVOID&)glutSetCursor, h_glutSetCursor);
printf("[Novidia] Hooking uploadModelTransformBuf\n");
DetourAttach(&(PVOID&)uploadModelTransformBuf, h_uploadModelTransformBuf);
printf("[Novidia] Hooking wglGetProcAddress\n");
DetourAttach(&(PVOID&)wGlGetProcAddress_forhook, h_wglGetProcAddress);
DetourTransactionCommit();
}
return TRUE;
}
using namespace PluginConfig;
extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
{
return L"Novidia";
}
extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
{
return L"Novidia by somewhatlurker\n\nPerforms some model skinning transformations in an alternate way to enable functionality on non-Nvidia hardware.\nAlso fixes crashing on non-Nvidia hardware.\n\nRequires patched shaders and GLIntercept installed to work.";
}
@@ -0,0 +1,49 @@
#pragma once
#include "glStuff.h"
// use this as a hook to perform initialisation
void(__cdecl* glutSetCursor)(int cursor) = *(void(__cdecl**)(int))0x140966068;
void(__cdecl* uploadModelTransformBuf)(DWORD* a1, int a2) = (void(__cdecl*)(DWORD * a1, int a2))0x140444fa0;
PROC(*wGlGetProcAddress_forhook)(LPCSTR) = (PROC(*)(LPCSTR))(GetProcAddress(GetModuleHandle(L"opengl32.dll"), "wglGetProcAddress"));;
bool& performTransform = *(bool*)0x14cc57bb0;
// vars that will contain the requiered info about GL buffers to perform the transform
GLuint buf_tex;
// check if a buffer target is okay to allow on non-Nvidia platforms
// (used to prevent crashes in glBindBuffer and glBufferData)
// only parameter buffer NV targets cause issues
bool checkBufferTargetOk(GLenum target)
{
return !(target == GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV || target == GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV);
}
int __stdcall stub() { return 1; }
/*
std::wstring ExePath() {
WCHAR buffer[MAX_PATH];
GetModuleFileNameW(NULL, buffer, MAX_PATH);
return std::wstring(buffer);
}
std::wstring DirPath() {
std::wstring exepath = ExePath();
std::wstring::size_type pos = exepath.find_last_of(L"\\/");
return exepath.substr(0, pos);
}
std::wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\Novidia.ini";
LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();
void loadConfig()
{
}
*/
@@ -0,0 +1,136 @@
#pragma once
#include <windows.h>
#include <iostream>
#include <detours.h>
// should probably just use GL.h, but I'm avoiding it to let me call hooked stuff as normal
typedef uint32_t GLenum, GLuint, GLsizei, GLbitfield;
typedef int32_t GLint;
typedef uint64_t GLsizeiptr;
typedef int64_t GLintptr, GLint64;
typedef bool GLboolean;
typedef char GLchar;
#define GL_FALSE 0
#define GL_NO_ERROR 0
#define GL_TEXTURE_1D 0x0de0
#define GL_FLOAT 0x1406
#define GL_RGBA 0x1908
#define GL_NEAREST 0x2600
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_CLAMP_TO_BORDER 0x812d
#define GL_CLAMP_TO_EDGE 0x812f
#define GL_TEXTURE0 0x84c0
#define GL_TEXTURE8 0x84c8
#define GL_BUFFER_SIZE 0x8764
#define GL_RGBA32F 0x8814
#define GL_ARRAY_BUFFER 0x8892
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_READ_ONLY 0x88b8
#define GL_STREAM_DRAW 0x88e0
#define GL_STREAM_COPY 0x88e2
#define GL_COMPILE_STATUS 0x8b81
#define GL_LINK_STATUS 0x8b82
#define GL_CURRENT_PROGRAM 0x8b8d
#define GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV 0x8da2
#define GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8da4
#define GL_SHADER_STORAGE_BUFFER 0x90d2
#define GL_COMPUTE_SHADER 0x91b9
#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
//void(__cdecl** p_glActiveTexture)(GLenum texture) = (void(__cdecl**)(GLenum texture))0x1411a3db8;
//void(__cdecl* glGenTextures)(GLsizei n, GLuint* textures) = *(void(__cdecl**)(GLsizei n, GLuint * textures))0x140965ad8;
//void(__cdecl* glBindTexture)(GLenum target, GLuint texture) = *(void(__cdecl**)(GLenum target, GLuint texture))0x140965bf8;
//void(__cdecl* glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void* indices) = *(void(__cdecl**)(GLenum mode, GLsizei count, GLenum type, const void* indices))0x140965a48;
// these are all dynamic imports and can't be initialised until after the OpenGL context is created
void(__cdecl* glActiveTexture)(GLenum texture);
void(__cdecl* glGenTextures)(GLsizei n, GLuint* textures);
void(__cdecl* glBindTexture)(GLenum target, GLuint texture);
void(__cdecl* glTexStorage1D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
//void(__cdecl* glTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void* pixels);
void(__cdecl* glTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void* pixels);
void(__cdecl* glTexParameteri)(GLenum target, GLenum pname, GLint param);
//void(__cdecl* glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices);
void(__cdecl* glBindBuffer)(GLenum target, GLuint buffer);
void(__cdecl* glBindBufferARB)(GLenum target, GLuint buffer);
void(__cdecl* glBufferData)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
void(__cdecl* glBufferDataARB)(GLenum target, GLsizeiptr size, const void* data, GLenum usage);
void(__cdecl* glFinish)();
// just used for a nicer time getting addresses and hooking
struct {
void* ptr;
const char* name;
bool dynamic;
} glFuncs[] = {
//{&glDrawElements, "glDrawElements", false},
{&glActiveTexture, "glActiveTexture", true},
{&glGenTextures, "glGenTextures", true},
{&glBindTexture, "glBindTexture", true},
{&glTexStorage1D, "glTexStorage1D", true},
//{&glTexImage1D, "glTexImage1D", true},
{&glTexSubImage1D, "glTexSubImage1D", true},
{&glTexParameteri, "glTexParameteri", true},
//{&glDrawRangeElements, "glDrawRangeElements", true},
{&glBindBuffer, "glBindBuffer", true},
{&glBindBufferARB, "glBindBufferARB", true},
{&glBufferData, "glBufferData", true},
{&glBufferDataARB, "glBufferDataARB", true},
{&glFinish, "glFinish", true},
};
bool loadGlAddresses()
{
bool ret = true;
for (auto fn : glFuncs)
{
if (fn.dynamic)
{
*(PROC*)(fn.ptr) = wglGetProcAddress(fn.name);
if (*(PROC*)(fn.ptr) == nullptr)
{
printf("[Novidia] Failed to load address of %s\n", fn.name);
ret = false;
}
}
}
return ret;
}
const char* getGlFuncName(void* func)
{
const char* name = NULL;
for (auto fn : glFuncs)
{
if (func == *(PROC*)(fn.ptr))
name = fn.name;
}
return name;
}
bool hookGlFunc(PROC* target, void* hook)
{
const char* name = getGlFuncName(*target);
if (name == nullptr)
{
printf("[Novidia] Invalid hook target at %p\n", *target);
return false;
}
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
printf("[Novidia] Hooking %s\n", name);
DetourAttach(&(PVOID&)*target, hook);
DetourTransactionCommit();
return true;
}