(still untested) More splitting and cleanup

This commit is contained in:
nastys
2021-09-19 19:42:47 +02:00
parent bb9301978b
commit 5919ab6ff6
12 changed files with 542 additions and 229 deletions
@@ -0,0 +1,99 @@
<?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>
<ProjectGuid>{84DBD504-6220-1BCE-A7E4-6799DAF7C5BF}</ProjectGuid>
<RootNamespace>CustoMixer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>CustoMixer</ProjectName>
</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>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</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'">
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetExt>.dva</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-d2FH4- /utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>evr.lib;mfplat.lib;mfuuid.lib;strmiids.lib;syelog.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalOptions>-d2:-FH4- %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<AdditionalOptions>-d2FH4- /utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>evr.lib;mfplat.lib;mfuuid.lib;syelog.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>-d2:-FH4- %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="PluginConfigApi.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="PluginConfigApi.h" />
</ItemGroup>
</Project>
@@ -0,0 +1,168 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <vector>
// resolution class to store and sort the width and height easily
class resolution
{
public:
unsigned int width;
unsigned int height;
resolution()
{
width = 0;
height = 0;
}
resolution(unsigned int width, unsigned int height)
{
resolution::width = width;
resolution::height = height;
}
bool operator ==(const resolution &res2)
{
return width == res2.width && height == res2.height;
}
// in comparisons width takes priority because it's usually displayed first
bool operator <(const resolution &res2)
{
if (width == res2.width)
return height < res2.height;
else
return width < res2.width;
}
bool operator >(const resolution &res2)
{
if (width == res2.width)
return height > res2.height;
else
return width > res2.width;
}
};
namespace PluginConfig
{
#pragma pack(push, 1)
enum ConfigType {
CONFIG_BOOLEAN,
CONFIG_NUMERIC,
CONFIG_STRING,
CONFIG_DROPDOWN_INDEX,
CONFIG_DROPDOWN_TEXT,
CONFIG_DROPDOWN_NUMBER,
CONFIG_RESOLUTION,
CONFIG_GROUP_START,
CONFIG_GROUP_END,
CONFIG_BUTTON,
CONFIG_SPACER
};
struct PluginConfigBooleanData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
bool defaultVal;
bool saveAsString;
};
struct PluginConfigNumericData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
int minVal;
int maxVal;
};
struct PluginConfigStringData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
bool useUtf8;
};
struct PluginConfigDropdownIndexData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<LPCWSTR> valueStrings;
};
struct PluginConfigDropdownTextData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
LPCWSTR defaultVal;
std::vector<LPCWSTR> valueStrings;
bool editable;
bool useUtf8;
};
struct PluginConfigDropdownNumberData {
LPCWSTR iniVarName;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
int defaultVal;
std::vector<int> valueInts;
bool editable;
};
struct PluginConfigResolutionData {
LPCWSTR iniVarName;
LPCWSTR iniVarName2;
LPCWSTR iniSectionName;
LPCWSTR iniFilePath;
LPCWSTR friendlyName;
LPCWSTR description;
resolution defaultVal;
std::vector<resolution> valueResolutions;
bool editable;
};
struct PluginConfigGroupData
{
LPCWSTR name;
int height;
};
struct PluginConfigButtonData {
LPCWSTR friendlyName;
LPCWSTR description;
void(*func)();
};
struct PluginConfigSpacerData {
int height;
};
struct PluginConfigOption
{
ConfigType cfgType;
void* data;
};
struct PluginConfigArray
{
int len;
PluginConfigOption* options;
};
#pragma pack(pop)
}
@@ -0,0 +1,180 @@
#include "PluginConfigApi.h"
#include "framework.h"
using namespace std;
int nNoHandScaling, nDefaultHandSize, nForceMouth, nForceExpressions, nForceLook;
void loadConfig()
{
nNoHandScaling = GetPrivateProfileIntW(L"patches", L"no_hand_scaling", FALSE, CONFIG_FILE) > 0 ? true : false;
nDefaultHandSize = GetPrivateProfileIntW(L"patches", L"default_hand_size", -1, CONFIG_FILE);
nForceMouth = GetPrivateProfileIntW(L"patches", L"force_mouth", 0, CONFIG_FILE);
nForceExpressions = GetPrivateProfileIntW(L"patches", L"force_expressions", 0, CONFIG_FILE);
nForceLook = GetPrivateProfileIntW(L"patches", L"force_look", 0, CONFIG_FILE);
return;
}
void pvPatches()
{
puts("[CustoMixer] Applying PV patches...");
// Force mouth animations
{
if (nForceMouth == 1) // PDA
{
printf("[CustoMixer] Forcing PDA mouth...\n");
int* mouth_table = (int*)(0x1409A1DC0);
DWORD oldProtect;
VirtualProtect(mouth_table, 44, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 11; i++)
{
mouth_table[i]++;
}
VirtualProtect(mouth_table, 44, oldProtect, nullptr);
printf("[CustoMixer] PDA mouth forced\n");
}
else if (nForceMouth == 2) // FT
{
printf("[CustoMixer] Forcing FT mouth...\n");
int* mouth_table_oldid = (int*)(0x1409A1E1C);
DWORD oldProtect;
VirtualProtect(mouth_table_oldid, 44, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 11; i++)
{
mouth_table_oldid[i]--;
}
VirtualProtect(mouth_table_oldid, 44, oldProtect, nullptr);
printf("[CustoMixer] FT mouth forced\n");
}
}
// Force expressions
{
if (nForceExpressions == 1) // PDA
{
printf("[CustoMixer] Forcing PDA expressions...\n");
int* exp_table = (int*)(0x140A21900);
DWORD oldProtect;
VirtualProtect(exp_table, 104, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 26; i++)
{
exp_table[i] += 2;
}
VirtualProtect(exp_table, 104, oldProtect, nullptr);
printf("[CustoMixer] PDA expressions forced\n");
}
else if (nForceExpressions == 2) // FT
{
printf("[CustoMixer] Forcing FT expressions...\n");
int* exp_table_oldid = (int*)(0x140A219D0);
DWORD oldProtect;
VirtualProtect(exp_table_oldid, 104, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 26; i++)
{
exp_table_oldid[i] -= 2;
}
VirtualProtect(exp_table_oldid, 104, oldProtect, nullptr);
printf("[CustoMixer] FT expressions forced\n");
}
}
// Force look animations
{
if (nForceLook == 1) // PDA
{
printf("[CustoMixer] Forcing PDA look...\n");
int* look_table = (int*)(0x1409A1D70);
DWORD oldProtect;
VirtualProtect(look_table, 36, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 9; i++)
{
look_table[i]++;
}
VirtualProtect(look_table, 36, oldProtect, nullptr);
printf("[CustoMixer] PDA look forced\n");
}
else if (nForceLook == 2) // FT
{
printf("[CustoMixer] Forcing FT look...\n");
int* look_table_oldid = (int*)(0x1409A1D9C);
DWORD oldProtect;
VirtualProtect(look_table_oldid, 36, PAGE_EXECUTE_READWRITE, &oldProtect);
for (int i = 0; i < 9; i++)
{
look_table_oldid[i]--;
}
VirtualProtect(look_table_oldid, 36, oldProtect, nullptr);
printf("[CustoMixer] FT look forced\n");
}
}
// Disable hand scaling
if (nNoHandScaling)
{
InjectCode((void*)0x0000000140120709, { 0xE9, 0x82, 0x0A, 0x00 });
}
// Default hand size
if (nDefaultHandSize != -1 && nDefaultHandSize < 1)
{
MessageBoxW(nullptr, L"The default hand size is lower than 1 and higher than -1 (default). Hands may disappear.\n\nIf this is not intentional, set it back to -1.", L"DivaWig", MB_ICONWARNING);
printf("[CustoMixer] Changing default hand size...\n");
const float num = (float)nDefaultHandSize / 10000.0;
DWORD oldProtect;
float* addr1 = (float*)(0x140506B59);
float* addr2 = (float*)(0x140506B60);
/*float* addr3 = (float*)(0x140506B67);
float* addr4 = (float*)(0x140506B71);*/
VirtualProtect(addr1, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
VirtualProtect(addr2, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
/*VirtualProtect(addr3, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
VirtualProtect(addr4, 4, PAGE_EXECUTE_READWRITE, &oldProtect);*/
*addr1 = *addr2 /*= *addr3 = *addr4*/ = num;
VirtualProtect(addr1, 4, oldProtect, nullptr);
VirtualProtect(addr2, 4, oldProtect, nullptr);
/*VirtualProtect(addr3, 4, oldProtect, nullptr);
VirtualProtect(addr4, 4, oldProtect, nullptr);*/
printf("[CustoMixer] New default hand size: %f\n", num);
}
puts("[CustoMixer] PV patches applied.");
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
loadConfig();
pvPatches();
}
return TRUE;
}
const std::vector<LPCWSTR> typeList = { L"Default", L"PDA", L"PDAFT/PDFT/PDM39" };
PluginConfig::PluginConfigOption config[] = {
{ PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"no_hand_scaling", L"patches", CONFIG_FILE, L"No Hand Scaling", L"Disable scripted hand scaling.", false } },
{ PluginConfig::CONFIG_NUMERIC, new PluginConfig::PluginConfigNumericData{ L"default_hand_size", L"patches", CONFIG_FILE, L"Default Hand Size:", L"-1: default\n12200: PDA", -1, -1, INT_MAX } },
{ PluginConfig::CONFIG_DROPDOWN_INDEX, new PluginConfig::PluginConfigDropdownIndexData{ L"force_mouth", L"patches", CONFIG_FILE, L"Mouth Animations:", L"Change the mouth animations.", 0, typeList}},
{ PluginConfig::CONFIG_DROPDOWN_INDEX, new PluginConfig::PluginConfigDropdownIndexData{ L"force_expressions", L"patches", CONFIG_FILE, L"Expr. Animations:", L"Change the expressions.", 0, typeList}},
{ PluginConfig::CONFIG_DROPDOWN_INDEX, new PluginConfig::PluginConfigDropdownIndexData{ L"force_look", L"patches", CONFIG_FILE, L"Look Animations:", L"Change the look animations.", 0, typeList}},
};
extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
{
return L"CustoMixer";
}
extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
{
return L"CustoMixer Plugin by nas\n\DivaWig lets you change some PV settings.";
}
extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void)
{
return PluginConfig::PluginConfigArray{ _countof(config), config };
}
@@ -0,0 +1,27 @@
#include <windows.h>
#include <string>
void InjectCode(void* address, const std::vector<uint8_t> data)
{
const size_t byteCount = data.size() * sizeof(uint8_t);
DWORD oldProtect;
VirtualProtect(address, byteCount, PAGE_EXECUTE_READWRITE, &oldProtect);
memcpy(address, data.data(), byteCount);
VirtualProtect(address, byteCount, oldProtect, nullptr);
}
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\\CustoMixer.ini";
LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();