Compare commits
6
Commits
DEV4fc2af28
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef43d22686 | ||
|
|
6ba220cc29 | ||
|
|
b20fc255dc | ||
|
|
cf26061123 | ||
|
|
3d422e4743 | ||
|
|
a4216507d6 |
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.28922.388
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.12.35527.113
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PD-Loader", "source\PD-Loader\PD-Loader.vcxproj", "{CA479467-D518-46A2-AC86-3098ADA99FE5}"
|
||||
EndProject
|
||||
|
||||
@@ -25,25 +25,28 @@ Toon_Hair_Improve=0
|
||||
Toon_Hair_Improve_Val1=1.25
|
||||
|
||||
# Lyb's toon shader improvements (24 sept 2019)
|
||||
# Fixes by korenkonder (11 jan 2025)
|
||||
# Toon_Lines_Improve: Adjusts toon shader outlines
|
||||
Toon_Lines_Improve=0
|
||||
# ???
|
||||
Toon_Lines_Improve_Val1=0.75
|
||||
# Thickness Multiplier(?)
|
||||
Toon_Lines_Improve_Val2=0.75
|
||||
# Thickness Offset(?)
|
||||
Toon_Lines_Improve_Val3=0.75
|
||||
# Skin Shadow Strength
|
||||
Toon_Lines_Improve_Val1=0.05
|
||||
# Skin Outline Strength
|
||||
Toon_Lines_Improve_Val2=0.9
|
||||
# Outline Strength Multiplier
|
||||
Toon_Lines_Improve_Val3=0.7
|
||||
# Outline Strength Offset
|
||||
Toon_Lines_Improve_Val4=0.25
|
||||
|
||||
[Patches]
|
||||
# Compatibility patches:
|
||||
# Star Story (and etc.) stage corruption (Maxwell+)
|
||||
blinn_per_vert\.0010010[23]00[01]\.fp=arch:AD,GA,GV,TU,GP,GM||cfg:compat||from:TEX tex_col, a_tex_color0, texture\[0\], 2D; ALIAS||to:TEX tex_col, a_tex_color0, texture[0], 2D; MUL tex_col, 1, tex_col; ALIAS
|
||||
blinn_per_vert\.0010010[23]00[01]\.fp=arch:GB,AD,GA,GV,TU,GP,GM||cfg:compat||from:TEX tex_col, a_tex_color0, texture\[0\], 2D; ALIAS||to:TEX tex_col, a_tex_color0, texture[0], 2D; MUL tex_col, 1, tex_col; ALIAS
|
||||
# Turing shading lines (new patch by samyuu, hopefully ported to here correctly)
|
||||
.*=arch:AD,GA,GV,TU||cfg:compat||from:SHORT ||to:
|
||||
.*=arch:GB,AD,GA,GV,TU||cfg:compat||from:SHORT ||to:
|
||||
# Turing NPR cloth noise
|
||||
cloth_npr1.*=arch:AD,GA,GV,TU||cfg:compat||from:SSG _tmp0.yw, ybr.xxzz;||to:TEMP _tmpForSSG; SGE _tmpForSSG.xz, ybr.xxzz, 0; SUB _tmpForSSG.xz, _tmpForSSG.xxzz, 1; SGT _tmpForSSG.yw, ybr.xxzz, 0; ADD _tmp0.yw, _tmpForSSG.xxzz, _tmpForSSG.yyww;
|
||||
cloth_npr1.*=arch:GB,AD,GA,GV,TU||cfg:compat||from:SSG _tmp0.yw, ybr.xxzz;||to:TEMP _tmpForSSG; SGE _tmpForSSG.xz, ybr.xxzz, 0; SUB _tmpForSSG.xz, _tmpForSSG.xxzz, 1; SGT _tmpForSSG.yw, ybr.xxzz, 0; ADD _tmp0.yw, _tmpForSSG.xxzz, _tmpForSSG.yyww;
|
||||
# Turing auto-exposure fix by samyuu
|
||||
stage_blinn.*\.fp=arch:AD,GA,GV,TU||cfg:compat||from:NRMH normal, a_normal;||to:NRM normal, a_normal;
|
||||
stage_blinn.*\.fp=arch:GB,AD,GA,GV,TU||cfg:compat||from:NRMH normal, a_normal;||to:NRM normal, a_normal;
|
||||
|
||||
# Lyb's toon shader improvements:
|
||||
cloth_npr1.*=cfg:toon_improve||from:MAD tmp.y, lc.z, 1.2, -0.5;||to:MAD tmp.y, lc.z, <val1>, <val2>;
|
||||
@@ -51,8 +54,9 @@ skin_default.*=cfg:toon_improve||from:MAD diff.xyz, spec, spec_ratio, diff;||to:
|
||||
.*eye.*=cfg:toon_eyes_improve||from:ADD o_color_f0.w, diff.x, diff.y;||to:
|
||||
.*eye.*=cfg:toon_eyes_improve||from:ADD result.color.w, diff.x, diff.y;||to:
|
||||
hair_npr1.*=cfg:toon_hair_improve||from:MUL spec.x, tmp.x, 0.7;||to:MUL spec.x, tmp.x, 0.7; MUL diff, diff, <val1>;
|
||||
tone_map_npr1.*=cfg:toon_lines_improve||from:MUL density.y, density.y, 0.25;||to:MUL density.y, density.y, <val1>;
|
||||
tone_map_npr1.*=cfg:toon_lines_improve||from:MAD density.w, density.x, 0.7, 0.25;||to:MAD density.w, density.x, <val2>, <val3>;
|
||||
tone_map_npr1.*=cfg:toon_lines_improve||from:MUL density.y, density.y, 0.05;||to:MUL density.y, density.y, <val1>;
|
||||
tone_map_npr1.*=cfg:toon_lines_improve||from:MUL density.y, density.y, 0.9;||to:MUL density.y, density.y, <val2>;
|
||||
tone_map_npr1.*=cfg:toon_lines_improve||from:MAD density.w, density.x, 0.7, 0.25;||to:MAD density.w, density.x, <val3>, <val4>;
|
||||
|
||||
# Intel related patches
|
||||
(?:movie|sprite|imgfilter).*=cfg:intel||from:; ||to:;\n
|
||||
|
||||
@@ -22,14 +22,17 @@ Toon_Hair_Improve=0
|
||||
Toon_Hair_Improve_Val1=1.25
|
||||
|
||||
# Lyb's toon shader improvements (24 sept 2019)
|
||||
# Fixes by korenkonder (11 jan 2025)
|
||||
# Toon_Lines_Improve: Adjusts toon shader outlines
|
||||
Toon_Lines_Improve=0
|
||||
# ???
|
||||
Toon_Lines_Improve_Val1=0.75
|
||||
# Thickness Multiplier(?)
|
||||
Toon_Lines_Improve_Val2=0.75
|
||||
# Thickness Offset(?)
|
||||
Toon_Lines_Improve_Val3=0.75
|
||||
# Skin Shadow Strength
|
||||
Toon_Lines_Improve_Val1=0.05
|
||||
# Skin Outline Strength
|
||||
Toon_Lines_Improve_Val2=0.9
|
||||
# Outline Strength Multiplier
|
||||
Toon_Lines_Improve_Val3=0.7
|
||||
# Outline Strength Offset
|
||||
Toon_Lines_Improve_Val4=0.25
|
||||
|
||||
# Debug patches:
|
||||
# Nametags
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Enable=1
|
||||
|
||||
[GPU]
|
||||
# Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell/Pascal, 2=Turing, 3=Ampere, 4=Ada Lovelace
|
||||
# Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell/Pascal, 2=Turing, 3=Ampere, 4=Ada Lovelace, 5=Blackwell
|
||||
Model=-1
|
||||
|
||||
[Launcher]
|
||||
@@ -35,6 +35,8 @@ Stereo=1
|
||||
Quick_Start=0
|
||||
#Disable the scrolling sound effect
|
||||
No_Scrolling_SFX=0
|
||||
#Automatically generate databank for missing entries and allow multiple PVList files to be used
|
||||
Auto_Databank=1
|
||||
#Enhanced Stage Manager (sets a custom number of stages; "stage_manager" should be disabled in "components.ini")
|
||||
#Number of stages (0 = disabled)
|
||||
Enhanced_Stage_Manager=0
|
||||
@@ -60,6 +62,8 @@ Hide_Volume=0
|
||||
No_PV_UI=0
|
||||
#Hide the watermark that's usually shown in PV viewing mode
|
||||
Hide_PV_Watermark=0
|
||||
#Hide the top-right corner status icons
|
||||
Hide_Status_Icons=0
|
||||
#Set the card reader and network status icons -- 0=default, 1=hidden, 2=error, 3=OK, 4=partial OK
|
||||
Status_Icons=0
|
||||
#Disable showing lyrics
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace GPUModel
|
||||
// note that the used GL context may differ
|
||||
std::string getGpuName()
|
||||
{
|
||||
// detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing, 3: Ampere, 4: Ada Lovelace
|
||||
// detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing, 3: Ampere, 4: Ada Lovelace, 5: Blackwell
|
||||
int nGPUModel = GetPrivateProfileIntW(L"gpu", L"model", -1, CONFIG_FILE);
|
||||
if (nGPUModel >= 0 && nGPUModel <= 4)
|
||||
{
|
||||
@@ -56,6 +56,9 @@ namespace GPUModel
|
||||
case 4:
|
||||
arch = "AD000";
|
||||
break;
|
||||
case 5:
|
||||
arch = "GB000";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("[GPUModel] GPU Model override: %s\n", arch.c_str());
|
||||
|
||||
@@ -166,7 +166,7 @@ ConfigOptionBase* internalResolutionArray[] = {
|
||||
};
|
||||
|
||||
ConfigOptionBase* graphicsArray[] = {
|
||||
new DropdownOption(L"model", L"GPU", CONFIG_FILE, L"Nvidia GPU:", L"Select your Nvidia GPU's architecture to apply the necessary workarounds.\n\nNOTE: Automatic detection does not currently work on GNU/Linux.", -1, std::vector<LPCWSTR>({ L"Automatic", L"Kepler", L"Maxwell/Pascal", L"Turing", L"Ampere", L"Ada or newer"}), -1),
|
||||
new DropdownOption(L"model", L"GPU", CONFIG_FILE, L"Nvidia GPU:", L"Select your Nvidia GPU's architecture to apply the necessary workarounds.\n\nNOTE: Automatic detection does not currently work on GNU/Linux.", -1, std::vector<LPCWSTR>({ L"Automatic", L"Kepler", L"Maxwell/Pascal", L"Turing", L"Ampere", L"Ada Lovelace", L"Blackwell or newer"}), -1),
|
||||
new BooleanOption(L"TAA", GRAPHICS_SECTION, CONFIG_FILE, L"TAA", L"Temporal Anti-Aliasing", true, false),
|
||||
new BooleanOption(L"MLAA", GRAPHICS_SECTION, CONFIG_FILE, L"MLAA", L"Morphological Anti-Aliasing", true, false),
|
||||
new DropdownOption(L"MAG", GRAPHICS_SECTION, CONFIG_FILE, L"Filter:", L"Image filter.\n\nBilinear: default filter\nNearest-neighbour: sharpest, but blocky\nSharpen: sharp filter\nCone: smooth filter", 0, std::vector<LPCWSTR>({ L"Bilinear", L"Nearest-neighbour", L"Sharpen", L"Cone" })),
|
||||
@@ -212,6 +212,7 @@ ConfigOptionBase* optionsArray[] = {
|
||||
new OptionMetaSpacer(8),
|
||||
|
||||
new OptionMetaSectionLabel(L"Stages/Songs"),
|
||||
new BooleanOption(L"Auto_Databank", PATCHES_SECTION, CONFIG_FILE, L"Auto Databank", L"Automatically generate databank for missing entries and allow multiple PvList files to be used.", true, false),
|
||||
new NumericOption(L"Enhanced_Stage_Manager", PATCHES_SECTION, CONFIG_FILE, L"Number of Stages:", L"Set the number of stages (0 = default).", 0, 0, INT_MAX),
|
||||
new BooleanOption(L"Enhanced_Stage_Manager_Encore", PATCHES_SECTION, CONFIG_FILE, L"Encore", L"Enable encore stages.", true, false),
|
||||
new BooleanOption(L"sing_missed", PATCHES_SECTION, CONFIG_FILE, L"Sing Missed", L"Sing missed notes.", false, false),
|
||||
@@ -233,7 +234,8 @@ ConfigOptionBase* optionsArray[] = {
|
||||
new BooleanOption(L"hide_volume", PATCHES_SECTION, CONFIG_FILE, L"Hide Volume Buttons", L"Hide the volume and SE control buttons.", false, false),
|
||||
new BooleanOption(L"no_pv_ui", PATCHES_SECTION, CONFIG_FILE, L"Disable PV UI", L"Remove the photo controls during PV playback.", false, false),
|
||||
new BooleanOption(L"hide_pv_watermark", PATCHES_SECTION, CONFIG_FILE, L"Hide PV Watermark", L"Hide the watermark that's usually shown in PV viewing mode.", false, false),
|
||||
new DropdownOption(L"status_icons", PATCHES_SECTION, CONFIG_FILE, L"Top-Right Network Icons:", L"Set the state of card reader and network status icons.", 3, std::vector<LPCWSTR>({ L"Default", L"Hidden", L"Error", L"OK", L"Partial OK" })),
|
||||
new BooleanOption(L"hide_status_icons", PATCHES_SECTION, CONFIG_FILE, L"Hide Network Icons", L"Hide the top-right corner status icons.", false, false), // technically reduntant, but somehow a lot of users miss the dropdown
|
||||
new DropdownOption(L"status_icons", PATCHES_SECTION, CONFIG_FILE, L"Network Icons Status:", L"Set the state of card reader and network status icons.", 3, std::vector<LPCWSTR>({ L"Default", L"Hidden", L"Error", L"OK", L"Partial OK" })),
|
||||
new BooleanOption(L"no_lyrics", PATCHES_SECTION, CONFIG_FILE, L"Disable Lyrics", L"Disable showing lyrics.", false, false),
|
||||
new BooleanOption(L"no_error", PATCHES_SECTION, CONFIG_FILE, L"Disable Error Banner", L"Disable the error banner on the attract screen.", true, false),
|
||||
new BooleanOption(L"hide_freeplay", PATCHES_SECTION, CONFIG_FILE, L"Hide \"FREE PLAY\"/\"CREDIT(S)\"", L"Hide the \"FREE PLAY\"/\"CREDIT(S)\" text.", false, false),
|
||||
|
||||
@@ -338,24 +338,36 @@ namespace Launcher {
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
|
||||
showGpuDialog = true;
|
||||
}
|
||||
else if (gpuModel->StartsWith("AD")) // unconfirmed??
|
||||
else if (gpuModel->StartsWith("GB")) // unconfirmed??
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: Blackwell GPU detected! Possible noise.\n(Click for more information)";
|
||||
GPUIssueText = L"On Blackwell GPUs (RTX 50xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled.";
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
|
||||
}
|
||||
else if (gpuModel->StartsWith("AD"))
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: Ada Lovelace GPU detected! Possible noise.\n(Click for more information)";
|
||||
GPUIssueText = L"On Ada Lovelace GPUs (RTX 40xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled.";
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
|
||||
}
|
||||
else if (gpuModel->StartsWith("GA")) // unconfirmed??
|
||||
else if (gpuModel->StartsWith("GA"))
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: Ampere GPU detected! Possible noise.\n(Click for more information)";
|
||||
GPUIssueText = L"On Ampere GPUs (RTX 30xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled.";
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
|
||||
}
|
||||
else if (gpuModel->StartsWith("TU") || gpuModel->StartsWith("GV")) // let's assume Volta is like Turing for now
|
||||
else if (gpuModel->StartsWith("TU"))
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: Turing GPU detected! Possible noise.\n(Click for more information)";
|
||||
GPUIssueText = L"On Turing GPUs (GTX 16xx/RTX 20xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled.";
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
|
||||
}
|
||||
else if (gpuModel->StartsWith("GV"))
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: Volta GPU detected! Possible noise.\n(Click for more information)";
|
||||
GPUIssueText = L"On Volta GPUs (TITAN V), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled.";
|
||||
this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
|
||||
}
|
||||
else if (gpuModel->StartsWith("GM") || gpuModel->StartsWith("GP"))
|
||||
{
|
||||
this->labelGPU->Text += L"Issues: May have minor noise on some stages.\n(Click for more information)";
|
||||
@@ -1192,8 +1204,8 @@ divagl_freeglut:
|
||||
return true;
|
||||
|
||||
divagl_novidia:
|
||||
SkinnedMessageBox::Show(this, "Plugins: Novidia and ShaderPatch must be disabled if DivaGL is enabled.", "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Error);
|
||||
return true;
|
||||
if (SkinnedMessageBox::Show(this, "Plugins: Novidia and ShaderPatch should be disabled if DivaGL is enabled.\n\nLaunch anyway?", "PD Launcher", MessageBoxButtons::YesNo, MessageBoxIcon::Error) != System::Windows::Forms::DialogResult::Yes)
|
||||
return true;
|
||||
|
||||
divagl_divaimguiold:
|
||||
SkinnedMessageBox::Show(this, "Plugins: Your version of DivaImGui is too old for DivaGL; please either update or disable it.", "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Error);
|
||||
|
||||
@@ -161,12 +161,18 @@ class PatchApplier600 : public PatchApplier {
|
||||
printf("[Patches] Cursor enabled\n");*/
|
||||
}
|
||||
// Override status icon states to be invalid (hides them)
|
||||
if (nStatusIcons > 0)
|
||||
if (nHideStatusIcons || nStatusIcons > 0)
|
||||
{
|
||||
std::vector<uint8_t> cardIcon = { 0xFD, 0x0A };
|
||||
std::vector<uint8_t> networkIcon = { 0x9E, 0x1E };
|
||||
|
||||
if (nStatusIcons == 2) // 2 for error icons
|
||||
if (nHideStatusIcons || nStatusIcons == 1 || nStatusIcons >= 5) // 1 or invalid for hidden
|
||||
{
|
||||
cardIcon = { 0xFD, 0x0A };
|
||||
networkIcon = { 0x9E, 0x1E };
|
||||
printf("[Patches] Status icons hidden\n");
|
||||
}
|
||||
else if (nStatusIcons == 2) // 2 for error icons
|
||||
{
|
||||
cardIcon = { 0xFA, 0x0A };
|
||||
networkIcon = { 0x9F, 0x1E };
|
||||
@@ -184,12 +190,6 @@ class PatchApplier600 : public PatchApplier {
|
||||
networkIcon = { 0xA1, 0x1E };
|
||||
printf("[Patches] Status icons set to partial OK state\n");
|
||||
}
|
||||
else // 1 or invalid for hidden
|
||||
{
|
||||
cardIcon = { 0xFD, 0x0A };
|
||||
networkIcon = { 0x9E, 0x1E };
|
||||
printf("[Patches] Status icons hidden\n");
|
||||
}
|
||||
|
||||
// card icon
|
||||
InjectCode((void*)0x00000001403A0C9E, cardIcon); // error state
|
||||
|
||||
@@ -180,12 +180,18 @@ class PatchApplier710 : public PatchApplier {
|
||||
printf("[Patches] Cursor enabled\n");
|
||||
}
|
||||
// Override status icon states to be invalid (hides them)
|
||||
if (nStatusIcons > 0)
|
||||
if (nHideStatusIcons || nStatusIcons > 0)
|
||||
{
|
||||
std::vector<uint8_t> cardIcon = { 0xFD, 0x0A };
|
||||
std::vector<uint8_t> networkIcon = { 0x9E, 0x1E };
|
||||
|
||||
if (nStatusIcons == 2) // 2 for error icons
|
||||
if (nHideStatusIcons || nStatusIcons == 1 || nStatusIcons >= 5) // 1 or invalid for hidden
|
||||
{
|
||||
cardIcon = { 0xFD, 0x0A };
|
||||
networkIcon = { 0x9E, 0x1E };
|
||||
printf("[Patches] Status icons hidden\n");
|
||||
}
|
||||
else if (nStatusIcons == 2) // 2 for error icons
|
||||
{
|
||||
cardIcon = { 0xFA, 0x0A };
|
||||
networkIcon = { 0x9F, 0x1E };
|
||||
@@ -203,12 +209,6 @@ class PatchApplier710 : public PatchApplier {
|
||||
networkIcon = { 0xA1, 0x1E };
|
||||
printf("[Patches] Status icons set to partial OK state\n");
|
||||
}
|
||||
else // 1 or invalid for hidden
|
||||
{
|
||||
cardIcon = { 0xFD, 0x0A };
|
||||
networkIcon = { 0x9E, 0x1E };
|
||||
printf("[Patches] Status icons hidden\n");
|
||||
}
|
||||
|
||||
// card icon
|
||||
InjectCode((void*)0x00000001403B9D6E, cardIcon); // error state
|
||||
|
||||
@@ -100,13 +100,17 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="databank.cpp" />
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="databank.h" />
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="PatchApplier.h" />
|
||||
<ClInclude Include="PatchApplier600.h" />
|
||||
<ClInclude Include="PatchApplier710.h" />
|
||||
<ClInclude Include="storage.h" />
|
||||
<ClInclude Include="urlutil.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="databank.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
@@ -32,5 +35,14 @@
|
||||
<ClInclude Include="PatchApplier710.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="databank.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="storage.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="urlutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,132 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "databank.h"
|
||||
#include "urlutil.h"
|
||||
|
||||
namespace Databank
|
||||
{
|
||||
bool PvList::readFromStr(std::string& str)
|
||||
{
|
||||
std::string decoded = urlDecode(urlDecode(str));
|
||||
|
||||
std::vector<std::string> tokens;
|
||||
std::stringstream ss(decoded);
|
||||
std::string token;
|
||||
while (std::getline(ss, token, ','))
|
||||
{
|
||||
if (!token.empty())
|
||||
{
|
||||
tokens.push_back(token);
|
||||
}
|
||||
}
|
||||
|
||||
if (tokens.size() % 7 != 0)
|
||||
{
|
||||
std::cerr << "[Patches] Databank error: Token count (" << tokens.size() << ") is not a multiple of 7." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < tokens.size(); i += 7)
|
||||
{
|
||||
try
|
||||
{
|
||||
PvEntry entry;
|
||||
std::tuple<int, int> id(std::stoi(tokens[i]), std::stoi(tokens[i + 2]));
|
||||
entry.unk1 = std::stoi(tokens[i + 1]);
|
||||
entry.advStart = tokens[i + 3];
|
||||
entry.advEnd = tokens[i + 4];
|
||||
entry.start = tokens[i + 5];
|
||||
entry.end = tokens[i + 6];
|
||||
entries.insert({ id, entry });
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "[Patches] Databank parse error: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PvList::readFromFile(const std::string& filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::ifstream file(filename, std::ios::in | std::ios::binary);
|
||||
if (!file)
|
||||
{
|
||||
std::cerr << "[Patches] Failed to open databank " + filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string contents = std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
||||
|
||||
return readFromStr(contents);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cerr << "[Patches] Databank file read error: " << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void PvList::addEntry(int id, int extra, PvEntry& entry)
|
||||
{
|
||||
entries.insert({ std::tuple<int, int>(id, extra), entry });
|
||||
}
|
||||
|
||||
void PvList::generateMissingEntries()
|
||||
{
|
||||
PvEntry entry = PvEntry();
|
||||
|
||||
for (int i = 0; i <= 999; i++)
|
||||
{
|
||||
entry.advStart = "2000-01-01";
|
||||
entry.advEnd = "2029-01-01";
|
||||
entry.start = "2000-01-01";
|
||||
entry.end = "2029-01-01";
|
||||
|
||||
entries.insert({ std::tuple<int, int>(i, 0), entry });
|
||||
entries.insert({ std::tuple<int, int>(i, 1), entry });
|
||||
}
|
||||
}
|
||||
|
||||
std::string PvList::finalize()
|
||||
{
|
||||
std::ostringstream csvStream;
|
||||
if (entries.empty())
|
||||
{
|
||||
return "%2A%2A%2A"; // ***
|
||||
//checksum = "5341";
|
||||
}
|
||||
else
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
for (const auto& entryMap : entries)
|
||||
{
|
||||
std::ostringstream entryStream;
|
||||
if (!first)
|
||||
{
|
||||
csvStream << ",";
|
||||
}
|
||||
first = false;
|
||||
const PvEntry& entry = entryMap.second;
|
||||
entryStream << std::get<0>(entryMap.first) << ","
|
||||
<< entry.unk1 << ","
|
||||
<< std::get<1>(entryMap.first) << ","
|
||||
<< entry.advStart << ","
|
||||
<< entry.advEnd << ","
|
||||
<< entry.start << ","
|
||||
<< entry.end;
|
||||
csvStream << urlEncode(entryStream.str());
|
||||
}
|
||||
|
||||
return urlEncode(csvStream.str());
|
||||
//checksum = std::to_string(crc16_ccitt(finalString));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
|
||||
#include "databank.h"
|
||||
|
||||
namespace Databank
|
||||
{
|
||||
struct PvEntry
|
||||
{
|
||||
int unk1 = 1;
|
||||
std::string advStart, advEnd, start, end;
|
||||
};
|
||||
|
||||
class PvList
|
||||
{
|
||||
protected:
|
||||
std::map<std::tuple<int, int>, PvEntry> entries;
|
||||
|
||||
public:
|
||||
bool readFromStr(std::string& str);
|
||||
bool readFromFile(const std::string& filename);
|
||||
void addEntry(int id, int extra, PvEntry& entry);
|
||||
void generateMissingEntries();
|
||||
std::string finalize();
|
||||
};
|
||||
}
|
||||
@@ -7,13 +7,16 @@
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <regex>
|
||||
#include <detours.h>
|
||||
|
||||
#include "PluginConfigApi.h"
|
||||
#include "PatchApplier.h"
|
||||
#include "PatchApplier600.h"
|
||||
#include "PatchApplier710.h"
|
||||
|
||||
#include <detours.h>
|
||||
#include "framework.h"
|
||||
#include "storage.h"
|
||||
#include "databank.h"
|
||||
#pragma comment(lib, "detours.lib")
|
||||
|
||||
unsigned short game_version = 710;
|
||||
@@ -22,7 +25,9 @@ void InjectCode(void* address, const std::vector<uint8_t> data);
|
||||
void ApplyPatches();
|
||||
void ApplyCustomPatches(std::wstring CPATCH_FILE_STRING);
|
||||
|
||||
|
||||
constexpr uint64_t PVLIST_INIT_ADDRESS = 0x000000014001EC80;
|
||||
void(__fastcall* divaPvListInitializer)(void* pvListContainer) = (void(__fastcall*)(void* pvListContainer))PVLIST_INIT_ADDRESS;
|
||||
void initPvListContainerHook();
|
||||
|
||||
HMODULE *hModulePtr;
|
||||
|
||||
@@ -98,6 +103,11 @@ void ApplyPatches() {
|
||||
|
||||
std::cout << "[Patches] All custom patches applied\n";
|
||||
}
|
||||
|
||||
if (nAutoDatabank)
|
||||
{
|
||||
initPvListContainerHook();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +254,7 @@ void ApplyCustomPatches(std::wstring CPATCH_FILE_STRING)
|
||||
if (echo) std::cout << std::endl;
|
||||
else if (comment_string.length() > 0)
|
||||
{
|
||||
std::cout << "[Patches]";;
|
||||
std::cout << "[Patches]";
|
||||
if (comment_string.at(0) != ' ') std::cout << ' ';
|
||||
std::cout << comment_string << std::endl;
|
||||
}
|
||||
@@ -254,6 +264,52 @@ void ApplyCustomPatches(std::wstring CPATCH_FILE_STRING)
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
Databank::PvList lists[5] = {};
|
||||
void hookedPvListInitializer(void* pvListContainer)
|
||||
{
|
||||
Storage::FileRecord* records = (Storage::FileRecord*)((uint64_t)pvListContainer + 0xA0);
|
||||
|
||||
for (int i = 0; i <= 4; i++)
|
||||
{
|
||||
std::regex pattern("(PvList" + std::to_string(i) +"_SBZV_7.10_.*_.*\\.dat)");
|
||||
try
|
||||
{
|
||||
for (const auto& entry : std::filesystem::directory_iterator("ram/databank/"))
|
||||
{
|
||||
if (entry.is_regular_file() && std::regex_match(entry.path().filename().string(), pattern))
|
||||
{
|
||||
std::string path = entry.path().string();
|
||||
std::cout << "[Patches] Reading databank: " << path << std::endl;
|
||||
lists[i].readFromFile(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::filesystem::filesystem_error& e)
|
||||
{
|
||||
std::cerr << "[Patches] Databank filesystem error: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
if (i != 4) lists[i].generateMissingEntries();
|
||||
std::string finalString = lists[i].finalize();
|
||||
|
||||
Storage::customAddStringContainer(&records[i], finalString.c_str());
|
||||
}
|
||||
|
||||
*(uint8_t*)(0x140CDB1D9) = 0x01; // enables databank
|
||||
}
|
||||
|
||||
void initPvListContainerHook()
|
||||
{
|
||||
if (game_version != 710) return;
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
DetourAttach(&(PVOID&)divaPvListInitializer, (PVOID)(hookedPvListInitializer));
|
||||
DetourTransactionCommit();
|
||||
std::cout << "[Patch] Auto Databank enabled" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
using namespace PluginConfig;
|
||||
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef uint16_t(__fastcall* p_crc16_ccitt)(void* data, int len);
|
||||
p_crc16_ccitt o_crc16_ccitt = (p_crc16_ccitt)0x140011A90;
|
||||
|
||||
uint16_t crc16_ccitt(std::string& str)
|
||||
{
|
||||
return o_crc16_ccitt(str.data(), str.size());
|
||||
}
|
||||
|
||||
std::string TrimString(const std::string& str, const std::string& whitespace)
|
||||
{
|
||||
const size_t strBegin = str.find_first_not_of(whitespace);
|
||||
@@ -91,6 +99,7 @@ auto nCursor = GetPrivateProfileIntW(L"patches", L"cursor", TRUE, CONFIG_FILE);
|
||||
auto nHideFreeplay = GetPrivateProfileIntW(L"patches", L"hide_freeplay", FALSE, CONFIG_FILE);
|
||||
auto nFreeplay = GetPrivateProfileIntW(L"patches", L"freeplay", TRUE, CONFIG_FILE);
|
||||
auto nPDLoaderText = GetPrivateProfileIntW(L"patches", L"pdloadertext", TRUE, CONFIG_FILE);
|
||||
auto nHideStatusIcons = GetPrivateProfileIntW(L"patches", L"hide_status_icons", FALSE, CONFIG_FILE);
|
||||
auto nStatusIcons = GetPrivateProfileIntW(L"patches", L"status_icons", 0, CONFIG_FILE);
|
||||
auto nHidePVWatermark = GetPrivateProfileIntW(L"patches", L"hide_pv_watermark", FALSE, CONFIG_FILE);
|
||||
auto nNoPVUi = GetPrivateProfileIntW(L"patches", L"no_pv_ui", FALSE, CONFIG_FILE);
|
||||
@@ -101,6 +110,7 @@ auto nMP4Movies = GetPrivateProfileIntW(L"patches", L"mp4_movies", FALSE, CONFIG
|
||||
auto nNoError = GetPrivateProfileIntW(L"patches", L"no_error", FALSE, CONFIG_FILE);
|
||||
auto nNoTimer = GetPrivateProfileIntW(L"patches", L"no_timer", TRUE, CONFIG_FILE);
|
||||
auto nNoTimerSprite = GetPrivateProfileIntW(L"patches", L"no_timer_sprite", TRUE, CONFIG_FILE);
|
||||
auto nAutoDatabank = GetPrivateProfileIntW(L"patches", L"auto_databank", TRUE, CONFIG_FILE);
|
||||
auto nEStageManager = GetPrivateProfileIntW(L"patches", L"enhanced_stage_manager", 0, CONFIG_FILE);
|
||||
auto nEStageManagerEncore = GetPrivateProfileIntW(L"patches", L"enhanced_stage_manager_encore", TRUE, CONFIG_FILE);
|
||||
auto nUnlockPseudo = GetPrivateProfileIntW(L"patches", L"unlock_pseudo", FALSE, CONFIG_FILE);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
namespace Storage
|
||||
{
|
||||
struct FileRecord
|
||||
{
|
||||
union
|
||||
{
|
||||
void* pData; // used if allocSize is >= 16
|
||||
char inlineData[16]; // used if allocSize is < 16; [8-15] not normally cleared when expanded
|
||||
};
|
||||
uint64_t dataLength = 0;
|
||||
uint64_t allocSize = 15;
|
||||
};
|
||||
|
||||
//void(__fastcall* divaAddStringContainer)(void*, void**) = (void(__fastcall*)(void* container, void** src))0x01400C0A40;
|
||||
|
||||
void customAddStringContainer(void* container, const char* str)
|
||||
{
|
||||
uint64_t addr = (uint64_t)container;
|
||||
|
||||
while (*(uint64_t*)addr != 0)
|
||||
{
|
||||
addr += sizeof(FileRecord);
|
||||
}
|
||||
|
||||
FileRecord* record = (FileRecord*)addr;
|
||||
size_t length = strlen(str) + 1;
|
||||
|
||||
if (length > 0 && length < 16)
|
||||
{
|
||||
memcpy_s(record->inlineData, length, str, length);
|
||||
record->dataLength = length;
|
||||
record->allocSize = 0;
|
||||
}
|
||||
else if (length >= 16)
|
||||
{
|
||||
char* alloc = (char*)malloc(length);
|
||||
memcpy_s(alloc, length, str, length);
|
||||
record->pData = alloc;
|
||||
record->dataLength = length;
|
||||
record->allocSize = length;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
std::string urlDecode(const std::string& encoded)
|
||||
{
|
||||
std::string decoded;
|
||||
char ch;
|
||||
for (size_t i = 0; i < encoded.length(); i++)
|
||||
{
|
||||
if (encoded[i] == '%')
|
||||
{
|
||||
if (i + 2 < encoded.length())
|
||||
{
|
||||
std::string hex = encoded.substr(i + 1, 2);
|
||||
ch = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
|
||||
decoded.push_back(ch);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded.push_back('%');
|
||||
}
|
||||
}
|
||||
else if (encoded[i] == '+')
|
||||
{
|
||||
decoded.push_back(' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
decoded.push_back(encoded[i]);
|
||||
}
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::string urlEncode(const std::string& str)
|
||||
{
|
||||
std::ostringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << std::hex;
|
||||
|
||||
for (unsigned char c : str)
|
||||
{
|
||||
if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
|
||||
{
|
||||
escaped << c;
|
||||
}
|
||||
else
|
||||
{
|
||||
escaped << '%' << std::setw(2) << std::uppercase << static_cast<int>(c);
|
||||
}
|
||||
}
|
||||
return escaped.str();
|
||||
}
|
||||
Reference in New Issue
Block a user