diff --git a/source-code/PD-Loader.sln b/source-code/PD-Loader.sln
index e7842d9..7ebb452 100644
--- a/source-code/PD-Loader.sln
+++ b/source-code/PD-Loader.sln
@@ -21,6 +21,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaMovie", "source\plugins
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShaderPatch", "source\plugins\ShaderPatch\ShaderPatch.vcxproj", "{C07E495E-A16F-48FA-80E4-0296B5234F0B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivaWig", "source\plugins\DivaWig\DivaWig.vcxproj", "{2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -63,6 +65,10 @@ Global
{C07E495E-A16F-48FA-80E4-0296B5234F0B}.Debug|x64.Build.0 = Debug|x64
{C07E495E-A16F-48FA-80E4-0296B5234F0B}.Release|x64.ActiveCfg = Release|x64
{C07E495E-A16F-48FA-80E4-0296B5234F0B}.Release|x64.Build.0 = Release|x64
+ {2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x64.ActiveCfg = Debug|x64
+ {2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Debug|x64.Build.0 = Debug|x64
+ {2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.ActiveCfg = Release|x64
+ {2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/source-code/source/plugins/DivaWig/DivaWig.vcxproj b/source-code/source/plugins/DivaWig/DivaWig.vcxproj
new file mode 100644
index 0000000..b84fb10
--- /dev/null
+++ b/source-code/source/plugins/DivaWig/DivaWig.vcxproj
@@ -0,0 +1,98 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ {2394C586-F73B-4EF2-BA3E-2A0FC3034B1A}
+ DivaWig
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v142
+ MultiByte
+
+
+ DynamicLibrary
+ false
+ v142
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .dva
+
+
+ .dva
+
+
+
+ Level3
+ Disabled
+ true
+ true
+ ..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)
+ -d2FH4- %(AdditionalOptions)
+
+
+ Console
+ ..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)
+ detours.lib;evr.lib;mfplat.lib;mfuuid.lib;strmiids.lib;syelog.lib;%(AdditionalDependencies)
+ -d2:-FH4- %(AdditionalOptions)
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ true
+ ..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)
+ MultiThreaded
+ -d2FH4- %(AdditionalOptions)
+
+
+ Console
+ true
+ true
+ detours.lib;evr.lib;mfplat.lib;mfuuid.lib;syelog.lib;%(AdditionalDependencies)
+ ..\..\..\dependencies\detours\lib;%(AdditionalLibraryDirectories)
+ -d2:-FH4- %(AdditionalOptions)
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source-code/source/plugins/DivaWig/DivaWig.vcxproj.filters b/source-code/source/plugins/DivaWig/DivaWig.vcxproj.filters
new file mode 100644
index 0000000..ce68d0f
--- /dev/null
+++ b/source-code/source/plugins/DivaWig/DivaWig.vcxproj.filters
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source-code/source/plugins/DivaWig/PluginConfigApi.h b/source-code/source/plugins/DivaWig/PluginConfigApi.h
new file mode 100644
index 0000000..d0ffd94
--- /dev/null
+++ b/source-code/source/plugins/DivaWig/PluginConfigApi.h
@@ -0,0 +1,168 @@
+#pragma once
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#include
+#include
+
+// 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 valueStrings;
+ };
+
+ struct PluginConfigDropdownTextData {
+ LPCWSTR iniVarName;
+ LPCWSTR iniSectionName;
+ LPCWSTR iniFilePath;
+ LPCWSTR friendlyName;
+ LPCWSTR description;
+ LPCWSTR defaultVal;
+ std::vector valueStrings;
+ bool editable;
+ bool useUtf8;
+ };
+
+ struct PluginConfigDropdownNumberData {
+ LPCWSTR iniVarName;
+ LPCWSTR iniSectionName;
+ LPCWSTR iniFilePath;
+ LPCWSTR friendlyName;
+ LPCWSTR description;
+ int defaultVal;
+ std::vector valueInts;
+ bool editable;
+ };
+
+ struct PluginConfigResolutionData {
+ LPCWSTR iniVarName;
+ LPCWSTR iniVarName2;
+ LPCWSTR iniSectionName;
+ LPCWSTR iniFilePath;
+ LPCWSTR friendlyName;
+ LPCWSTR description;
+ resolution defaultVal;
+ std::vector 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)
+}
\ No newline at end of file
diff --git a/source-code/source/plugins/DivaWig/dllmain.cpp b/source-code/source/plugins/DivaWig/dllmain.cpp
new file mode 100644
index 0000000..be2c4e9
--- /dev/null
+++ b/source-code/source/plugins/DivaWig/dllmain.cpp
@@ -0,0 +1,185 @@
+#include "framework.h"
+#include "PluginConfigApi.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define HEAD_ACCESSORY 0
+#define HAIR 1
+#define UNKNOWN_1 2
+#define UNKNOWN_2 3
+#define FACE_ACCESSORY 4
+#define UNKNOWN_3 5
+#define FACE_TEXTURES 6
+#define UNKNOWN_4 7
+#define CHEST_ACCESSORY 8
+#define UNKNOWN_5 9
+#define BODY 10
+#define UNKNOWN_6 11
+#define UNKNOWN_7 12
+#define UNKNOWN_8 13
+#define HANDS 14,
+#define UNKNOWN_9 15
+#define BACK_ACCESSORY 16
+#define UNKNOWN_10 17
+#define UNKNOWN_11 18
+#define UNKNOWN_12 19
+#define UNKNOWN_13 20
+#define UNKNOWN_14 21
+#define UNKNOWN_15 22
+#define UNKNOWN_16 23
+#define HEAD 24
+
+void(__cdecl* originalWig)(void* cls, uint64_t unk, uint64_t unk2) = (void(__cdecl*)(void* cls, uint64_t unk, uint64_t unk2))0x14052AD90;
+const std::string Strings[25] = { "Head accessory", "Hair", "Unknown 1", "Unknown 2", "Face accessory", "Unknown 3", "Face textures", "Unknown 4", "Chest accessory", "Unknown 5", "Body", "Unknown 6", "Unknown 7", "Unknown 8", "Hands", "Unknown 9", "Back accessory", "Unknown 10", "Unknown 11", "Unknown 12", "Unknown 13", "Unknown 14", "Unknown 15", "Unknown 16", "Head" };
+bool only_hair = false, only_head_accessory = false, only_face_accessory = false, only_face_textures = false, head = false, nothing = false;
+
+void loadConfig()
+{
+ // some_option = GetPrivateProfileIntW(L"general", L"some_option", 0, CONFIG_FILE) > 0 ? true : false;
+
+ return;
+}
+
+void inputLoop()
+{
+ while (true)
+ {
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('0') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = false;
+ only_face_accessory = false;
+ only_face_textures = false;
+ head = false;
+ nothing = false;
+ Beep(330, 300);
+ std::cout << "[DivaWig] Update all module parts!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('1') < 0)
+ {
+ only_hair = true;
+ only_head_accessory = false;
+ only_face_accessory = false;
+ only_face_textures = false;
+ head = false;
+ nothing = false;
+ Beep(440, 300);
+ std::cout << "[DivaWig] Only update the hair!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('2') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = true;
+ only_face_accessory = false;
+ only_face_textures = false;
+ head = false;
+ nothing = false;
+ Beep(550, 300);
+ std::cout << "[DivaWig] Only update the head accessory!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('3') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = false;
+ only_face_accessory = true;
+ only_face_textures = false;
+ head = false;
+ nothing = false;
+ Beep(660, 300);
+ std::cout << "[DivaWig] Only update the face accessory!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('4') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = false;
+ only_face_accessory = false;
+ only_face_textures = true;
+ head = false;
+ nothing = false;
+ Beep(770, 300);
+ std::cout << "[DivaWig] Only update the face textures!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('5') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = false;
+ only_face_accessory = false;
+ only_face_textures = false;
+ head = true;
+ nothing = false;
+ Beep(880, 300);
+ std::cout << "[DivaWig] Only update the head!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ if ((GetKeyState(VK_LCONTROL) < 0 || GetKeyState(VK_RCONTROL) < 0) && GetKeyState('9') < 0)
+ {
+ only_hair = false;
+ only_head_accessory = false;
+ only_face_accessory = false;
+ only_face_textures = false;
+ head = false;
+ nothing = true;
+ Beep(220, 300);
+ std::cout << "[DivaWig] Update nothing!" << std::endl;
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ }
+}
+
+__int64 hookedWig(__int64 classp, int module_part, int part_id)
+{
+ std::cout << "[DivaWig] Performer: " << (classp-5387286232)/33040+1 << "; Module part: " << module_part << " (" << Strings[module_part] << ")" << "; Default part: " << part_id << "." << std::endl;
+
+ if (!(only_hair || only_head_accessory || only_face_accessory || only_face_textures || head || nothing) || (only_hair && module_part == HAIR) || (only_head_accessory && module_part == HEAD_ACCESSORY) || (only_face_accessory && module_part == FACE_ACCESSORY) || (only_face_textures && module_part == FACE_TEXTURES) || (head && module_part == HEAD))
+ *(int*)(classp + 4i64 * module_part + 8) = part_id;
+
+ return module_part;
+}
+
+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());
+ std::cout << "[DivaWig] Hooking function..." << std::endl;
+ DetourAttach(&(PVOID&)originalWig, (PVOID)hookedWig);
+ std::cout << "[DivaWig] Function hooked." << std::endl;
+ DetourTransactionCommit();
+
+ std::thread* inputThread = new std::thread(inputLoop);
+ }
+
+ return TRUE;
+}
+
+/*PluginConfig::PluginConfigOption config[] = {
+ { PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"some_option", L"general", CONFIG_FILE, L"TODO", L"Add options.", false } },
+};*/
+
+extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
+{
+ return L"DivaWig";
+}
+
+extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
+{
+ return L"DivaWig Plugin by nas\n\nDivaWig lets you mix some module parts.";
+}
+
+/*extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void)
+{
+ return PluginConfig::PluginConfigArray{ _countof(config), config };
+}*/
\ No newline at end of file
diff --git a/source-code/source/plugins/DivaWig/framework.h b/source-code/source/plugins/DivaWig/framework.h
new file mode 100644
index 0000000..740c11e
--- /dev/null
+++ b/source-code/source/plugins/DivaWig/framework.h
@@ -0,0 +1,17 @@
+#include
+#include
+
+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\\DivaWig.ini";
+LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();