19 Commits
Author SHA1 Message Date
nastys 1c026e2661 Update repo URL 2022-01-27 14:00:28 +01:00
nastys bef5d481a5 Launcher hotfix 2021-11-10 22:47:21 +01:00
nastys ea159ed465 Update mdata SFV 2021-10-27 18:14:45 +02:00
nastys 8b5b514368 2.6.5a: [DivaMovie] Change "hardware decoding" to "hybrid decoding" to avoid confusion 2021-10-08 12:34:17 +02:00
nastys 66db5deb2b 2.6.5a: Fix PlayerData, auto-disable DivaMovie if DXVA-HW is available (unless forced - fixes random black backgrounds) 2021-10-07 23:10:40 +02:00
nastys e8c2ac672a 2.6.5a: DivaMovie enabled by default again, but warns the user if it should be disabled 2021-10-07 19:04:48 +02:00
nastys 7df98ea648 2.6.5: macOS and Linux fixes, fix refl/refr patches 2021-10-07 16:31:11 +02:00
nastys 162cc52c6b 2.6.4: forgot to move termination byte (oops) 2021-09-29 19:29:03 +02:00
nastys c2343f79f2 2.6.4: PD Loader version text fix 2021-09-29 19:24:07 +02:00
nastys ea968b1762 2.6.4: replace refl/refr default option with 512x256 and restore uint type 2021-09-29 19:13:21 +02:00
nastys 4149a3c8e9 2.6.3: fix reflect/refract data type pt3 2021-09-29 19:05:08 +02:00
nastys d8693781ba 2.6.3: fix reflect/refract data type pt2 2021-09-29 19:03:57 +02:00
nastys 49e2b03159 2.6.2: fix reflect/refract data type 2021-09-29 19:01:44 +02:00
nastys bc925fd514 2.6.2: maximum hand size 100X, pv customization toggle, fix typo in Credits, option for disabling custom refract/refrect res, version in-game 2021-09-29 18:13:11 +02:00
nastys b511bf64c3 2.6b: fix display resolution combobox 2021-09-23 22:13:40 +02:00
nastys db159fde81 2.6a: bug fixes 2021-09-23 00:28:00 +02:00
nastys 4ebc4b3f85 2.6: start.bat, quick start warning, fully fix hand size, gamma control, fix coin, customizable toon key, rumble intensity, error 998 explaination, divawig enum, launcher option tab cleanup, gpu driver version detection, precise lag compensation, 7.10 check 2021-09-20 22:12:41 +02:00
nastys f93dab0b9a (2.5.3) Fix hand size 2021-09-04 23:18:23 +02:00
nastys eb17a30a06 (2.5.2) Fix manual Turing GPU; work around hand size upgrade error 2021-09-04 20:34:52 +02:00
34 changed files with 9613 additions and 25965 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
############################################################################### ###############################################################################
# Set default behavior to automatically normalize line endings. # Set default behavior to automatically normalize line endings.
############################################################################### ###############################################################################
* text=auto * binary
############################################################################### ###############################################################################
# Set default behavior for command prompt diff. # Set default behavior for command prompt diff.
+3
View File
@@ -1,3 +1,6 @@
._*
.DS_Store
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
+2 -2
View File
@@ -15000,8 +15000,8 @@ source code}{}}}\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\
\par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch \par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch
For information on getting and installing the latest release,} For information on getting and installing the latest release,}
\par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch \par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch
please read the wiki at }{{\field{\*\fldinst HYPERLINK "https://notabug.org/PDModdingCommunity/PD-Loader/wiki" }{\fldrslt {\rtlch\dbch\af8\hich\af5 \ltrch\langfe255\cf9\lang255\ul\ulc0\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch please read the wiki at }{{\field{\*\fldinst HYPERLINK "https://github.com/PDModdingCommunity/PD-Loader/wiki" }{\fldrslt {\rtlch\dbch\af8\hich\af5 \ltrch\langfe255\cf9\lang255\ul\ulc0\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch
https://notabug.org/PDModdingCommunity/PD-Loader/wiki}}}} https://github.com/PDModdingCommunity/PD-Loader/wiki}}}}
\par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch \par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200{\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch
If you've already read it, pay more attention and you'll find the right link.} If you've already read it, pay more attention and you'll find the right link.}
\par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch \par \pard\plain \s0\dbch\af6\langfe1081\dbch\af7\afs24\alang1081\ql\nowidctlpar\hyphpar0\ltrpar\cf0\loch\f3\fs24\lang1040\kerning1\sl276\slmult1\ql\sb0\sa200\rtlch\dbch\af8\hich\af5 \ltrch\fs22\lang16\ulnone\ulc0\b0\loch\f5\loch
+1 -1
View File
@@ -3,7 +3,7 @@ If you just wanted to play the game, you downloaded the wrong thing.
Do not click the download button next to the git URL, that's for the source code. Do not click the download button next to the git URL, that's for the source code.
For information on getting and installing the latest release, For information on getting and installing the latest release,
please read the wiki at https://notabug.org/nastys/PD-Loader/wiki please read the wiki at https://github.com/nastys/PD-Loader/wiki
If you've already read it, pay more attention and you'll find the right link. If you've already read it, pay more attention and you'll find the right link.
You should also read the wiki if you have any issues, before asking questions. You should also read the wiki if you have any issues, before asking questions.
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://dotnet.microsoft.com/download/dotnet-framework/net48
+2
View File
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://www.quicksfv.org/qsfv236x64.exe
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://aka.ms/vs/16/release/vc_redist.x64.exe
+1 -1
View File
@@ -2,5 +2,5 @@
Prop3=19,11 Prop3=19,11
[InternetShortcut] [InternetShortcut]
IDList= IDList=
URL=https://notabug.org/PDModdingCommunity/PD-Loader/wiki URL=https://github.com/PDModdingCommunity/PD-Loader/wiki
HotKey=0 HotKey=0
Binary file not shown.
+9 -5
View File
@@ -7,7 +7,7 @@
Enable=1 Enable=1
[GPU] [GPU]
# Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell, 2=Turing, 3=Ampere # Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell/Pascal, 2=Turing, 3=Ampere
Model=-1 Model=-1
[Launcher] [Launcher]
@@ -25,7 +25,7 @@ OpenGL_Patch_A=0
OpenGL_Patch_B=0 OpenGL_Patch_B=0
# Command line arguments # Command line arguments
Command_Line= Command_Line=
# Launches divahook.bat intead of diva.exe. # Launches divahook.bat/start.bat intead of diva.exe.
Use_divahook_bat=0 Use_divahook_bat=0
[Patches] [Patches]
@@ -38,7 +38,7 @@ Cursor=1
#Use 2 channels instead of 4 (when not using DivaSound) #Use 2 channels instead of 4 (when not using DivaSound)
Stereo=1 Stereo=1
#Skip one or more menus -- 0=disabled, 1=guest, 2=guest+normal #Skip one or more menus -- 0=disabled, 1=guest, 2=guest+normal
Quick_Start=1 Quick_Start=0
#Disable the scrolling sound effect #Disable the scrolling sound effect
No_Scrolling_SFX=0 No_Scrolling_SFX=0
#Enhanced Stage Manager (sets a custom number of stages; "stage_manager" should be disabled in "components.ini") #Enhanced Stage Manager (sets a custom number of stages; "stage_manager" should be disabled in "components.ini")
@@ -46,6 +46,8 @@ No_Scrolling_SFX=0
Enhanced_Stage_Manager=0 Enhanced_Stage_Manager=0
#Use encore stages or not #Use encore stages or not
Enhanced_Stage_Manager_Encore=1 Enhanced_Stage_Manager_Encore=1
#Enable PV Customization below
Enable_PV_Customization=0
#Change the mouth animations -- 0=default, 1=force PDA, 2=force FT #Change the mouth animations -- 0=default, 1=force PDA, 2=force FT
Force_Mouth=0 Force_Mouth=0
#Change the expressions -- 0=default, 1=force PDA, 2=force FT #Change the expressions -- 0=default, 1=force PDA, 2=force FT
@@ -54,8 +56,8 @@ Force_Expressions=0
Force_Look=0 Force_Look=0
#Disable hand scaling #Disable hand scaling
No_Hand_Scaling=0 No_Hand_Scaling=0
#Default hand size -- -1=default, 12200=PDA #Default hand size -- 0-10000=default, 12200=PDA, 1000000=maximum
Default_Hand_Size=-1 Default_Hand_Size_uint=0
#Sing missed notes #Sing missed notes
Sing_Missed=0 Sing_Missed=0
#Hide the volume and SE control buttons #Hide the volume and SE control buttons
@@ -111,6 +113,8 @@ MAG=0
DOF=1 DOF=1
# Reflections # Reflections
Reflections=1 Reflections=1
# Gamma -- 0 or 100=default, 125=console-like
Gamma=100
# Shadows # Shadows
Shadows=1 Shadows=1
# Transparent Meshes # Transparent Meshes
@@ -24,7 +24,9 @@ VID = 046D
PID = C216 PID = C216
# Rumble (Xinput) # Rumble (Xinput)
rumble =true rumble = true
xinput_rumble_intensity_left = 8000
xinput_rumble_intensity_right = 4000
# Pause when focus is lost # Pause when focus is lost
autopause =true autopause =true
@@ -59,6 +61,7 @@ MENU_L = Left, Up, Ds4_L1, XINPUT_LS, Ds4_DPad_Left, Ds4_DPad_Up, XINPUT_LEFT, X
MENU_R = Right, Down, Ds4_R1, XINPUT_RS, Ds4_DPad_Right, Ds4_DPad_Down, XINPUT_RIGHT, XINPUT_DOWN, E, O, Ds4_L_Stick_Right, XINPUT_LRIGHT, Ds4_L_Stick_Down, XINPUT_LDOWN, Ds4_R_Stick_Right, XINPUT_RRIGHT, Ds4_R_Stick_Down, XINPUT_RDOWN MENU_R = Right, Down, Ds4_R1, XINPUT_RS, Ds4_DPad_Right, Ds4_DPad_Down, XINPUT_RIGHT, XINPUT_DOWN, E, O, Ds4_L_Stick_Right, XINPUT_LRIGHT, Ds4_L_Stick_Down, XINPUT_LDOWN, Ds4_R_Stick_Right, XINPUT_RRIGHT, Ds4_R_Stick_Down, XINPUT_RDOWN
MENU_CIRCLE = Spacebar MENU_CIRCLE = Spacebar
TOON = F9
COIN = F10 COIN = F10
# Touch Slider: # Touch Slider:
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -36,7 +36,7 @@ namespace GPUModel
{ {
// detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing, 3: Ampere // detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing, 3: Ampere
int nGPUModel = GetPrivateProfileIntW(L"gpu", L"model", -1, CONFIG_FILE); int nGPUModel = GetPrivateProfileIntW(L"gpu", L"model", -1, CONFIG_FILE);
if (nGPUModel >= 0 && nGPUModel <= 2) if (nGPUModel >= 0 && nGPUModel <= 3)
{ {
std::string arch; std::string arch;
switch (nGPUModel) switch (nGPUModel)
+4 -2
View File
@@ -184,7 +184,7 @@ void LoadDVA(std::wstring &path, LPCWSTR dir, LPCWSTR fileName)
msg.append(L"\n\nIs the Microsoft Visual C++ Redistributable for Visual Studio 2019 (x64) installed?"); msg.append(L"\n\nIs the Microsoft Visual C++ Redistributable for Visual Studio 2019 (x64) installed?");
break; break;
case 998: case 998:
msg.append(L"\n\nAre all dependencies installed?\nIf the problem persists, please disable this plugin."); msg.append(L"\n\nPossible causes:\n- a dependency is not installed; or\n- GPU detection failed (select the GPU Type manually/force Novidia in its Config).");
break; break;
default: default:
msg.append(L"\n\nAre all dependencies installed?"); msg.append(L"\n\nAre all dependencies installed?");
@@ -215,6 +215,8 @@ void FindFiles(WIN32_FIND_DATAW* fd)
do { do {
if (!(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (!(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{ {
if (fd->cFileName[0] == '.' && fd->cFileName[1] == '_') continue; // exclude macOS metadata
auto pos = wcslen(fd->cFileName); auto pos = wcslen(fd->cFileName);
if (fd->cFileName[pos - 4] == '.' && if (fd->cFileName[pos - 4] == '.' &&
@@ -771,7 +773,7 @@ void Init()
(PathFileExistsW(SHADERPATCH_TEMPLATE) && !PathFileExistsW(SHADERPATCH)) || (PathFileExistsW(SHADERPATCH_TEMPLATE) && !PathFileExistsW(SHADERPATCH)) ||
(PathFileExistsW(SHADERPATCHCONFIG_TEMPLATE) && !PathFileExistsW(SHADERPATCHCONFIG)) (PathFileExistsW(SHADERPATCHCONFIG_TEMPLATE) && !PathFileExistsW(SHADERPATCHCONFIG))
) )
MessageBoxW(0, L"Could not install configuration files. Is the game in a read-only folder?", L"PD Loader", MB_ICONWARNING); MessageBoxW(0, L"Could not install configuration files. Possible causes:\n\n- PD Loader was not installed correctly\n- The game is on a read-only drive\n- No privileges to write in the folder", L"PD Loader", MB_ICONWARNING);
CreateDirectoryW(L"plugins\\pv_equip", NULL); CreateDirectoryW(L"plugins\\pv_equip", NULL);
const auto eq_modules = L"plugins\\pv_equip\\modules.ini"; const auto eq_modules = L"plugins\\pv_equip\\modules.ini";
@@ -54,7 +54,7 @@
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\..\dependencies\simpleini;..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-d2FH4- %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>-d2FH4- %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
<Link> <Link>
@@ -72,7 +72,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\..\..\dependencies\simpleini;..\..\..\dependencies\detours\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<AdditionalOptions>-d2FH4- %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>-d2FH4- %(AdditionalOptions)</AdditionalOptions>
</ClCompile> </ClCompile>
@@ -10,8 +10,9 @@
#include <mfapi.h> #include <mfapi.h>
#include <mferror.h> #include <mferror.h>
#include <mftransform.h> #include <mftransform.h>
#include <SimpleIni.h>
bool forceSoftwareDecoding = false, debug = false; bool forceSoftwareDecoding = false, forceHybridDecoding = false, debug = false;
IDirect3DDeviceManager9* deviceManager; IDirect3DDeviceManager9* deviceManager;
@@ -146,6 +147,22 @@ VTABLE_HOOK(HRESULT, IMFTransform, ProcessMessage, MFT_MESSAGE_TYPE eMessage, UL
if (SUCCEEDED(result)) if (SUCCEEDED(result))
INSTALL_VTABLE_HOOK(This, ProcessOutput, 25); INSTALL_VTABLE_HOOK(This, ProcessOutput, 25);
} }
else if (!forceHybridDecoding && eMessage == MFT_MESSAGE_SET_D3D_MANAGER && result == 0)
{
static bool warn = false;
if (!warn)
{
MessageBoxW(0, L"Your system supports DXVA hardware decoding.\nDivaMovie will be disabled.\n\nIt is highly recommended to restart the game now.", L"DivaMovie", MB_ICONWARNING);
CSimpleIniW ini_reader;
ini_reader.SetUnicode(false);
ini_reader.LoadFile(MASTER_CONFIG_FILE);
ini_reader.SetValue(L"plugins", L"DivaMovie.dva", L"0");
ini_reader.SaveFile(MASTER_CONFIG_FILE);
warn = true;
}
}
return result; return result;
} }
@@ -177,6 +194,7 @@ HOOK(HRESULT, DXVA2CreateDirect3DDeviceManager, PROC_ADDRESS("dxva2.dll", "DXVA2
void loadConfig() { void loadConfig() {
forceSoftwareDecoding = GetPrivateProfileIntW(L"general", L"force_software_decoding", 0, CONFIG_FILE) > 0 ? true : false; forceSoftwareDecoding = GetPrivateProfileIntW(L"general", L"force_software_decoding", 0, CONFIG_FILE) > 0 ? true : false;
forceHybridDecoding = GetPrivateProfileIntW(L"general", L"force_hybrid_decoding", 0, CONFIG_FILE) > 0 ? true : false;
debug = GetPrivateProfileIntW(L"general", L"debug", 0, CONFIG_FILE) > 0 ? true : false; debug = GetPrivateProfileIntW(L"general", L"debug", 0, CONFIG_FILE) > 0 ? true : false;
} }
@@ -194,7 +212,8 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
PluginConfig::PluginConfigOption config[] = { PluginConfig::PluginConfigOption config[] = {
{ PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"force_software_decoding", L"general", CONFIG_FILE, L"Force Software Decoding", L"Use software decoding even on systems that support DXVA hardware decoding.", false } }, { PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"force_software_decoding", L"general", CONFIG_FILE, L"Force Software Decoding", L"Use software decoding even on systems that support DXVA hardware decoding.", false } },
{ PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"debug", L"general", CONFIG_FILE, L"Debug", L"Enable PRINT (possibly at the cost of performance).", false } }, { PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"force_hybrid_decoding", L"general", CONFIG_FILE, L"Force Hybrid Decoding", L"Do not disable DivaMovie on systems that support DXVA hardware decoding.\nCan cause issues on recent drivers.", false } },
{ PluginConfig::CONFIG_BOOLEAN, new PluginConfig::PluginConfigBooleanData{ L"debug", L"general", CONFIG_FILE, L"Debug (slow!)", L"Enable PRINT (possibly at the cost of performance).", false } },
}; };
extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void) extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
@@ -204,7 +223,7 @@ extern "C" __declspec(dllexport) LPCWSTR GetPluginName(void)
extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void) extern "C" __declspec(dllexport) LPCWSTR GetPluginDescription(void)
{ {
return L"DivaMovie Plugin by Skyth\n\nDivaMovie enables movies on systems that does not support DXVA hardware decoding."; return L"DivaMovie Plugin by Skyth\n\nDivaMovie enables movies on systems that do not support DXVA hardware decoding.";
} }
extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void) extern "C" __declspec(dllexport) PluginConfig::PluginConfigArray GetPluginOptions(void)
@@ -22,6 +22,9 @@ std::wstring DirPath() {
std::wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\DivaMovie.ini"; std::wstring CONFIG_FILE_STRING = DirPath() + L"\\plugins\\DivaMovie.ini";
LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str(); LPCWSTR CONFIG_FILE = CONFIG_FILE_STRING.c_str();
std::wstring MASTER_CONFIG_FILE_STRING = DirPath() + L"\\plugins\\config.ini";
LPCWSTR MASTER_CONFIG_FILE = MASTER_CONFIG_FILE_STRING.c_str();
#define PRINT(value, ...) if (debug) printf(value, __VA_ARGS__); #define PRINT(value, ...) if (debug) printf(value, __VA_ARGS__);
#define PROC_ADDRESS(libraryName, procName) \ #define PROC_ADDRESS(libraryName, procName) \
+30 -27
View File
@@ -7,33 +7,36 @@
#include <tchar.h> #include <tchar.h>
#include <thread> #include <thread>
#define HEAD_ACCESSORY 0 static const enum module_part
#define HAIR 1 {
#define UNKNOWN_1 2 HEAD_ACCESSORY,
#define UNKNOWN_2 3 HAIR,
#define FACE_ACCESSORY 4 UNKNOWN_1,
#define UNKNOWN_3 5 UNKNOWN_2,
#define FACE_TEXTURES 6 FACE_ACCESSORY,
#define UNKNOWN_4 7 UNKNOWN_3,
#define CHEST_ACCESSORY 8 FACE_TEXTURES,
#define UNKNOWN_5 9 UNKNOWN_4,
#define BODY 10 CHEST_ACCESSORY,
#define UNKNOWN_6 11 UNKNOWN_5,
#define UNKNOWN_7 12 BODY,
#define UNKNOWN_8 13 UNKNOWN_6,
#define HANDS 14, UNKNOWN_7,
#define UNKNOWN_9 15 UNKNOWN_8,
#define BACK_ACCESSORY 16 HANDS,
#define UNKNOWN_10 17 UNKNOWN_9,
#define UNKNOWN_11 18 BACK_ACCESSORY,
#define UNKNOWN_12 19 UNKNOWN_10,
#define UNKNOWN_13 20 UNKNOWN_11,
#define UNKNOWN_14 21 UNKNOWN_12,
#define UNKNOWN_15 22 UNKNOWN_13,
#define UNKNOWN_16 23 UNKNOWN_14,
#define HEAD 24 UNKNOWN_15,
#define ALL -1 UNKNOWN_16,
#define NONE -2 HEAD,
ALL = -1,
NONE = -2
};
using namespace std; using namespace std;
@@ -33,6 +33,7 @@ Panel^ MakePanel(int width, int height, std::vector<ConfigOptionBase*> &cfg, Too
#define RESOPT_MATCH_WINDOW_TEXT "Match Window" #define RESOPT_MATCH_WINDOW_TEXT "Match Window"
#define RESOPT_MATCH_SCREEN_TEXT "Match Screen" #define RESOPT_MATCH_SCREEN_TEXT "Match Screen"
#define RESOPT_DEFAULT_TEXT "Default"
ref class ComboboxValidation ref class ComboboxValidation
{ {
@@ -81,7 +82,7 @@ public:
{ {
System::String^ text = cb->Text; System::String^ text = cb->Text;
if (text == RESOPT_MATCH_WINDOW_TEXT || text == RESOPT_MATCH_SCREEN_TEXT) if (text == RESOPT_MATCH_WINDOW_TEXT || text == RESOPT_MATCH_SCREEN_TEXT || text == RESOPT_DEFAULT_TEXT)
return; return;
cli::array<Char>^ digitsarray = gcnew cli::array<Char>{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9' }; cli::array<Char>^ digitsarray = gcnew cli::array<Char>{ L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9' };
@@ -285,6 +286,43 @@ public:
} }
}; };
class OptionMetaSectionLabel : public ConfigOptionBase
{
public:
OptionMetaSectionLabel(LPCWSTR friendlyName)
{
_friendlyName = friendlyName;
}
virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip)
{
Label^ lab = gcnew Label();
lab->Text = gcnew String(_friendlyName);
lab->Left = left + 2;
lab->Top = top;
lab->Font = gcnew System::Drawing::Font(lab->Font->Name, 12.0f, System::Drawing::FontStyle::Bold);
lab->AutoSize = true;
Form^ RootForm = panel->FindForm();
float ScaleWidth = 1.0f;
float ScaleHeight = 1.0f;
if (RootForm)
{
Drawing::SizeF CurrentScaleSize = RootForm->CurrentAutoScaleDimensions;
ScaleWidth = CurrentScaleSize.Width / BaseScaleSize;
ScaleHeight = CurrentScaleSize.Height / BaseScaleSize;
}
lab->Scale(ScaleWidth, ScaleHeight);
panel->Controls->Add(lab);
mainControlHandle = lab->Handle;
int ControlHeight = lab->Font->Height / ScaleHeight;
return ControlHeight + ControlSpacing;
}
};
class OptionMetaSpacer : public ConfigOptionBase class OptionMetaSpacer : public ConfigOptionBase
{ {
public: public:
@@ -849,8 +887,10 @@ public:
enum ResolutionOptionOpts enum ResolutionOptionOpts
{ {
RESOPT_INCLUDE_MATCH_WINDOW = 1, RESOPT_NONE,
RESOPT_INCLUDE_MATCH_SCREEN = 2 RESOPT_INCLUDE_MATCH_WINDOW,
RESOPT_INCLUDE_MATCH_SCREEN,
RESOPT_INCLUDE_DEFAULT = 4
}; };
class ResolutionOption : public ConfigOptionBase class ResolutionOption : public ConfigOptionBase
@@ -894,6 +934,8 @@ public:
combobox->Items->Add(RESOPT_MATCH_WINDOW_TEXT); combobox->Items->Add(RESOPT_MATCH_WINDOW_TEXT);
else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN) else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN)
combobox->Items->Add(RESOPT_MATCH_SCREEN_TEXT); combobox->Items->Add(RESOPT_MATCH_SCREEN_TEXT);
else if (_opts & RESOPT_INCLUDE_DEFAULT)
combobox->Items->Add(RESOPT_DEFAULT_TEXT);
for (resolution& choice : _valueResolutions) { for (resolution& choice : _valueResolutions) {
tempSysStr = Convert::ToInt32(choice.width).ToString() + L"x" + Convert::ToInt32(choice.height).ToString(); tempSysStr = Convert::ToInt32(choice.width).ToString() + L"x" + Convert::ToInt32(choice.height).ToString();
@@ -916,6 +958,8 @@ public:
combobox->Text = RESOPT_MATCH_WINDOW_TEXT; combobox->Text = RESOPT_MATCH_WINDOW_TEXT;
else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN) else if (_opts & RESOPT_INCLUDE_MATCH_SCREEN)
combobox->Text = RESOPT_MATCH_SCREEN_TEXT; combobox->Text = RESOPT_MATCH_SCREEN_TEXT;
else if (_opts & RESOPT_INCLUDE_DEFAULT)
combobox->Text = RESOPT_DEFAULT_TEXT;
} }
else { else {
tempSysStr = Convert::ToInt32(width).ToString() + L"x" + Convert::ToInt32(height).ToString(); tempSysStr = Convert::ToInt32(width).ToString() + L"x" + Convert::ToInt32(height).ToString();
@@ -976,7 +1020,7 @@ public:
tempSysStr = ((ComboBox^)ComboBox::FromHandle(mainControlHandle))->Text; tempSysStr = ((ComboBox^)ComboBox::FromHandle(mainControlHandle))->Text;
// Match window/screen -> -1x-1 // Match window/screen -> -1x-1
if (tempSysStr == RESOPT_MATCH_WINDOW_TEXT || tempSysStr == RESOPT_MATCH_SCREEN_TEXT) if (tempSysStr == RESOPT_MATCH_WINDOW_TEXT || tempSysStr == RESOPT_MATCH_SCREEN_TEXT || tempSysStr == RESOPT_DEFAULT_TEXT)
tempSysStr = "-1x-1"; tempSysStr = "-1x-1";
resolutionArray = tempSysStr->Split('x'); resolutionArray = tempSysStr->Split('x');
+51 -35
View File
@@ -95,6 +95,11 @@ std::vector<resolution> getScreenResolutionsVec(std::vector<DEVMODEW> &screenMod
} }
} }
const resolution defaultres(1280, 720);
if (std::find(outVec.begin(), outVec.end(), defaultres) == outVec.end()) {
outVec.push_back(defaultres);
}
std::sort(outVec.begin(), outVec.end()); std::sort(outVec.begin(), outVec.end());
return outVec; return outVec;
@@ -139,19 +144,21 @@ static std::vector<int> getScreenRatesVec(std::vector<DEVMODEW> &screenModes) {
std::vector<DEVMODEW> screenModes = getScreenModes(); std::vector<DEVMODEW> screenModes = getScreenModes();
const std::vector<resolution> internalResOptions = { resolution(320,240), resolution(426,240), resolution(640,480), resolution(854,480), resolution(960,540), resolution(1280,720), resolution(1366,768), resolution(1600,900), resolution(1920,1080), resolution(2560,1440), resolution(3200,1800), resolution(3840,2160), resolution(5120,2880), resolution(7680,4320) };
DropdownOption* DisplayModeDropdown = new DropdownOption(L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 1, std::vector<LPCWSTR>({ L"Windowed", L"Fast", L"Exclusive", L"Safe" })); DropdownOption* DisplayModeDropdown = new DropdownOption(L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 1, std::vector<LPCWSTR>({ L"Windowed", L"Fast", L"Exclusive", L"Safe" }));
ResolutionOption* DisplayResolutionOption = new ResolutionOption(L"width", L"height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the display resolution.", resolution(-1, -1), getScreenResolutionsVec(screenModes), true, RESOPT_INCLUDE_MATCH_SCREEN); ResolutionOption* DisplayResolutionOption = new ResolutionOption(L"width", L"height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the display resolution.", resolution(-1, -1), getScreenResolutionsVec(screenModes), true, RESOPT_INCLUDE_MATCH_SCREEN);
DropdownNumberOption* RefreshRateOption = new DropdownNumberOption(L"refreshrate", RESOLUTION_SECTION, CONFIG_FILE, L"Refresh Rate:", L"Sets the display refresh rate.", 60, getScreenRatesVec(screenModes), true);
ConfigOptionBase* screenResolutionArray[] = { ConfigOptionBase* screenResolutionArray[] = {
DisplayModeDropdown, DisplayModeDropdown,
DisplayResolutionOption, DisplayResolutionOption,
//new DropdownNumberOption(L"bitdepth", RESOLUTION_SECTION, CONFIG_FILE, L"Bit Depth:", L"Sets the display bit depth.", 32, getScreenDepthsVec(screenModes), true), //new DropdownNumberOption(L"bitdepth", RESOLUTION_SECTION, CONFIG_FILE, L"Bit Depth:", L"Sets the display bit depth.", 32, getScreenDepthsVec(screenModes), true),
new DropdownNumberOption(L"refreshrate", RESOLUTION_SECTION, CONFIG_FILE, L"Refresh Rate:", L"Sets the display refresh rate.", 60, getScreenRatesVec(screenModes), true), RefreshRateOption,
}; };
BooleanOption* InternalResolutionCheckbox = new BooleanOption(L"r.enable", RESOLUTION_SECTION, CONFIG_FILE, L"Enable", L"Enable or disable custom internal resolution.", false, false); BooleanOption* InternalResolutionCheckbox = new BooleanOption(L"r.enable", RESOLUTION_SECTION, CONFIG_FILE, L"Enable", L"Enable or disable custom internal resolution.", false, false);
ResolutionOption* InternalResolutionOption = new ResolutionOption(L"r.width", L"r.height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the internal resolution (instead of 1280x720).", resolution(1920, 1080), std::vector<resolution>({ resolution(1,1), resolution(320,240), resolution(426,240), resolution(640,480), resolution(854,480), resolution(960,540), resolution(1280,720), resolution(1366,768), resolution(1600,900), resolution(1920,1080), resolution(2560,1440), resolution(3200,1800), resolution(3840,2160), resolution(5120,2880), resolution(7680,4320) }), true, RESOPT_INCLUDE_MATCH_WINDOW); ResolutionOption* InternalResolutionOption = new ResolutionOption(L"r.width", L"r.height", RESOLUTION_SECTION, CONFIG_FILE, L"Resolution:", L"Sets the internal resolution (instead of 1280x720).", resolution(1920, 1080), internalResOptions, true, RESOPT_INCLUDE_MATCH_WINDOW);
ConfigOptionBase* internalResolutionArray[] = { ConfigOptionBase* internalResolutionArray[] = {
InternalResolutionCheckbox, InternalResolutionCheckbox,
@@ -159,14 +166,15 @@ ConfigOptionBase* internalResolutionArray[] = {
}; };
ConfigOptionBase* graphicsArray[] = { 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", L"Turing", L"Ampere" }), -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" }), -1),
new BooleanOption(L"TAA", GRAPHICS_SECTION, CONFIG_FILE, L"TAA", L"Temporal Anti-Aliasing", true, false), 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 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" })), 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" })),
new BooleanOption(L"DOF", GRAPHICS_SECTION, CONFIG_FILE, L"Depth of Field", L"Blurs the background. Disable for better performance.", true, false), new BooleanOption(L"DOF", GRAPHICS_SECTION, CONFIG_FILE, L"Depth of Field", L"Blurs the background. Disable for better performance.", true, false),
new BooleanOption(L"reflections", GRAPHICS_SECTION, CONFIG_FILE, L"Reflections", L"Enable or disable reflections.", true, false), new BooleanOption(L"reflections", GRAPHICS_SECTION, CONFIG_FILE, L"Reflections", L"Enable or disable reflections.", true, false),
new ResolutionOption(L"reflect_res_width", L"reflect_res_height", GRAPHICS_SECTION, CONFIG_FILE, L"Reflection Res:", L"Sets the reflection buffer resolution (instead of 512x256).", resolution(512, 256), std::vector<resolution>({resolution(256,256), resolution(512,256), resolution(512,512), resolution(1024,1024), resolution(2048,2048), resolution(4096,4096)}), true, (ResolutionOptionOpts)0), new ResolutionOption(L"reflect_res_width", L"reflect_res_height", GRAPHICS_SECTION, CONFIG_FILE, L"Reflection Res:", L"Sets the reflection buffer resolution (instead of 512x256).", resolution(512, 256), std::vector<resolution>({resolution(256,256), resolution(512,256), resolution(512,512), resolution(1024,1024), resolution(2048,2048), resolution(4096,4096)}), true, RESOPT_NONE),
new ResolutionOption(L"refract_res_width", L"refract_res_height", GRAPHICS_SECTION, CONFIG_FILE, L"Refraction Res:", L"Sets the refraction buffer resolution (instead of 512x256).", resolution(512, 256), std::vector<resolution>({resolution(256,256), resolution(512,256), resolution(512,512), resolution(1024,1024), resolution(2048,2048), resolution(4096,4096)}), true, (ResolutionOptionOpts)0), new ResolutionOption(L"refract_res_width", L"refract_res_height", GRAPHICS_SECTION, CONFIG_FILE, L"Refraction Res:", L"Sets the refraction buffer resolution (instead of 512x256).", resolution(512, 256), std::vector<resolution>({resolution(256,256), resolution(512,256), resolution(512,512), resolution(1024,1024), resolution(2048,2048), resolution(4096,4096)}), true, RESOPT_NONE),
new NumericOption(L"gamma", GRAPHICS_SECTION, CONFIG_FILE, L"Gamma:", L"Increase to darken shadows.\nSet to 125 for a console-like experience.\n\nDefault: 0 or 100", 100, 0, 200),
new BooleanOption(L"shadows", GRAPHICS_SECTION, CONFIG_FILE, L"Shadows", L"Enable or disable shadows.", true, false), new BooleanOption(L"shadows", GRAPHICS_SECTION, CONFIG_FILE, L"Shadows", L"Enable or disable shadows.", true, false),
new BooleanOption(L"punchthrough", GRAPHICS_SECTION, CONFIG_FILE, L"Transparent Meshes", L"Show transparent meshes.", true, false), new BooleanOption(L"punchthrough", GRAPHICS_SECTION, CONFIG_FILE, L"Transparent Meshes", L"Show transparent meshes.", true, false),
new BooleanOption(L"glare", GRAPHICS_SECTION, CONFIG_FILE, L"Glare", L"Enable or disable glare.", true, false), new BooleanOption(L"glare", GRAPHICS_SECTION, CONFIG_FILE, L"Glare", L"Enable or disable glare.", true, false),
@@ -177,6 +185,7 @@ ConfigOptionBase* graphicsArray[] = {
}; };
ConfigOptionBase* optionsArray[] = { ConfigOptionBase* optionsArray[] = {
new OptionMetaSectionLabel(L"Compatibility"),
new BooleanOption(L"no_movies", PATCHES_SECTION, CONFIG_FILE, L"Disable Movies", L"Disable movies (enable this if the game hangs when loading certain PVs).", false, false), new BooleanOption(L"no_movies", PATCHES_SECTION, CONFIG_FILE, L"Disable Movies", L"Disable movies (enable this if the game hangs when loading certain PVs).", false, false),
new BooleanOption(L"mp4_movies", PATCHES_SECTION, CONFIG_FILE, L"Custom MP4 Adv Movies", L"Enable MP4 (instead of WMV) advertise/attract movies.", false, false), new BooleanOption(L"mp4_movies", PATCHES_SECTION, CONFIG_FILE, L"Custom MP4 Adv Movies", L"Enable MP4 (instead of WMV) advertise/attract movies.", false, false),
new BooleanOption(L"cursor", PATCHES_SECTION, CONFIG_FILE, L"Cursor", L"Enable or disable the mouse cursor.", true, false), new BooleanOption(L"cursor", PATCHES_SECTION, CONFIG_FILE, L"Cursor", L"Enable or disable the mouse cursor.", true, false),
@@ -184,25 +193,42 @@ ConfigOptionBase* optionsArray[] = {
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"Controller Options"),
new BooleanOption(L"rumble", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"XInput Rumble", L"Enables rumble during chainslides.", true, true),
new NumericOption(L"xinput_rumble_intensity_left", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"Left motor:", L"Left rumble motor intensity (XInput).\n\nDefault: 8000", 8000, 0, USHRT_MAX),
new NumericOption(L"xinput_rumble_intensity_right", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"Right motor:", L"Right rumble motor intensity (XInput).\n\nDefault: 4000", 4000, 0, USHRT_MAX),
new NumericOption(L"xinput_preferred", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"XInput Controller Num:", L"Sets the preferred XInput controller.\nIf unavailable, the next connected controller is used.", 0, 0, 3),
new BooleanOption(L"hardware_slider", PATCHES_SECTION, CONFIG_FILE, L"Use Hardware Slider", L"Enable this if using a real arcade slider.\n(set the slider to port COM11)", false, false),
new OptionMetaSeparator(),
new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"PV Selector"),
new DropdownOption(L"quick_start", PATCHES_SECTION, CONFIG_FILE, L"Quick Start:", L"Skip one or more menus.", 1, std::vector<LPCWSTR>({ L"Disabled", L"Guest", L"Guest + Normal" })), new DropdownOption(L"quick_start", PATCHES_SECTION, CONFIG_FILE, L"Quick Start:", L"Skip one or more menus.", 1, std::vector<LPCWSTR>({ L"Disabled", L"Guest", L"Guest + Normal" })),
new BooleanOption(L"no_scrolling_sfx", PATCHES_SECTION, CONFIG_FILE, L"Disable Scrolling SFX", L"Disable the scrolling sound effect.", false, false), new BooleanOption(L"no_scrolling_sfx", PATCHES_SECTION, CONFIG_FILE, L"Disable Scrolling SFX", L"Disable the scrolling sound effect.", false, false),
new BooleanOption(L"unlock_pseudo", PATCHES_SECTION, CONFIG_FILE, L"Unlock PSEUDO modules (incomplete)", L"Lets you play any PV with any performer.\n(incomplete, recommended modules will default to Miku)", false, false),
new BooleanOption(L"card", PATCHES_SECTION, CONFIG_FILE, L"Unlock card menu (incomplete)", L"Enables the card menu.\n(incomplete, it doesn't bypass the card prompt)", false, false),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"Stages/Songs"),
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 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"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),
new BooleanOption(L"autopause", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"Pause Automatically", L"Pause when focus is lost.", true, true),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"PV Customization"),
new BooleanOption(L"enable_pv_customization", PATCHES_SECTION, CONFIG_FILE, L"Enable PV Customization", L"Enable the options below.", false, false),
new DropdownOption(L"force_mouth", PATCHES_SECTION, CONFIG_FILE, L"Mouth Type:", L"Change the mouth animations.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })), new DropdownOption(L"force_mouth", PATCHES_SECTION, CONFIG_FILE, L"Mouth Type:", L"Change the mouth animations.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })),
new DropdownOption(L"force_expressions", PATCHES_SECTION, CONFIG_FILE, L"Expression Type:", L"Change the expressions.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })), new DropdownOption(L"force_expressions", PATCHES_SECTION, CONFIG_FILE, L"Expression Type:", L"Change the expressions.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })),
new DropdownOption(L"force_look", PATCHES_SECTION, CONFIG_FILE, L"Look Type:", L"Change the look animations.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })), new DropdownOption(L"force_look", PATCHES_SECTION, CONFIG_FILE, L"Look Type:", L"Change the look animations.", 0, std::vector<LPCWSTR>({ L"Default", L"Force PDA", L"Force FT" })),
new BooleanOption(L"no_hand_scaling", PATCHES_SECTION, CONFIG_FILE, L"No Hand Scaling", L"Disable hand scaling.", false, false), new BooleanOption(L"no_hand_scaling", PATCHES_SECTION, CONFIG_FILE, L"No Hand Scaling", L"Disable hand scaling.", false, false),
new NumericOption(L"default_hand_size", PATCHES_SECTION, CONFIG_FILE, L"Default Hand Size:", L"-1: default\n12200: PDA", -1, -1, INT_MAX), new NumericOption(L"default_hand_size_uint", PATCHES_SECTION, CONFIG_FILE, L"Default Hand Size:", L"0-10000: default\n12200: PDA\n1000000: maximum", 0, 0, 1000000),
new BooleanOption(L"sing_missed", PATCHES_SECTION, CONFIG_FILE, L"Sing Missed", L"Sing missed notes.", false, false),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"UI Elements"),
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"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"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 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),
@@ -217,46 +243,32 @@ ConfigOptionBase* optionsArray[] = {
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new BooleanOption(L"unlock_pseudo", PATCHES_SECTION, CONFIG_FILE, L"Unlock PSEUDO modules (incomplete)", L"Lets you play any PV with any performer.\n(incomplete, recommended modules will default to Miku)", false, false), new OptionMetaSectionLabel(L"Framerate"),
new BooleanOption(L"card", PATCHES_SECTION, CONFIG_FILE, L"Unlock card menu (incomplete)", L"Enables the card menu.\n(incomplete, it doesn't bypass the card prompt)", false, false),
new OptionMetaSeparator(),
new OptionMetaSpacer(8),
new BooleanOption(L"FPS.Limit.LightMode", GRAPHICS_SECTION, CONFIG_FILE, L"Use Lightweight Limiter", L"Makes the FPS limiter use less CPU.\nMay have less consistent performance.", true, false), new BooleanOption(L"FPS.Limit.LightMode", GRAPHICS_SECTION, CONFIG_FILE, L"Use Lightweight Limiter", L"Makes the FPS limiter use less CPU.\nMay have less consistent performance.", true, false),
new NumericOption(L"FPS.Limit", GRAPHICS_SECTION, CONFIG_FILE, L"FPS Limit:", L"Allows you to set a frame rate cap. Set to -1 to unlock the frame rate.", 60, -1, INT_MAX), new NumericOption(L"FPS.Limit", GRAPHICS_SECTION, CONFIG_FILE, L"FPS Limit:", L"Allows you to set a frame rate cap. Set to -1 to unlock the frame rate.", 60, -1, INT_MAX),
new NumericOption(L"frm.motion.rate", GRAPHICS_SECTION, CONFIG_FILE, L"FRM Motion Rate:", L"Sets the motion rate (fps) for the Frame Rate Manager component.\nLarger values should be smoother, but more CPU intensive and possibly buggier.", 300, 1, INT_MAX), new NumericOption(L"frm.motion.rate", GRAPHICS_SECTION, CONFIG_FILE, L"FRM Motion Rate:", L"Sets the motion rate (fps) for the Frame Rate Manager component.\nLarger values should be smoother, but more CPU intensive and possibly buggier.", 300, 1, INT_MAX),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new BooleanOption(L"autopause", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"Pause Automatically", L"Pause when focus is lost.", true, true), new OptionMetaSectionLabel(L"Advanced Compatibility"),
new OptionMetaSeparator(),
new OptionMetaSpacer(8),
new BooleanOption(L"rumble", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"XInput Rumble", L"Enables rumble during chainslides.", true, true),
new NumericOption(L"xinput_preferred", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"XInput Controller Num:", L"Sets the preferred XInput controller.\nIf unavailable, the next connected controller is used.", 0, 0, 3),
new OptionMetaSeparator(),
new OptionMetaSpacer(8),
new BooleanOption(L"hardware_slider", PATCHES_SECTION, CONFIG_FILE, L"Use Hardware Slider", L"Enable this if using a real arcade slider.\n(set the slider to port COM11)", false, false),
new OptionMetaSeparator(),
new OptionMetaSpacer(8),
new BooleanOption(L"opengl_patch_a", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch A", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false), new BooleanOption(L"opengl_patch_a", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch A", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false),
new BooleanOption(L"opengl_patch_b", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch B", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false), new BooleanOption(L"opengl_patch_b", LAUNCHER_SECTION, CONFIG_FILE, L"OpenGL Patch B", L"Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing.", false, false),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"Loader"),
new BooleanOption(L"custom_patches", PATCHES_SECTION, CONFIG_FILE, L"Enable Custom Patches", L"Enables all custom patches.", true, false), new BooleanOption(L"custom_patches", PATCHES_SECTION, CONFIG_FILE, L"Enable Custom Patches", L"Enables all custom patches.", true, false),
//new BooleanOption(L"ignore_exe_checksum", PATCHES_SECTION, CONFIG_FILE, L"Ignore exe checksum", L"Use at your own risk.", false, false),
new BooleanOption(L"prevent_data_deletion", PATCHES_SECTION, CONFIG_FILE, L"Prevent Data Deletion", L"Prevents the game from deleting files.", false, false), new BooleanOption(L"prevent_data_deletion", PATCHES_SECTION, CONFIG_FILE, L"Prevent Data Deletion", L"Prevents the game from deleting files.", false, false),
new StringOption(L"command_line", LAUNCHER_SECTION, CONFIG_FILE, L"Command Line:", L"Allows setting command line parameters for the game when using the launcher.\nDisabling the launcher will bypass this.", L"", false),
new BooleanOption(L"use_divahook_bat", LAUNCHER_SECTION, CONFIG_FILE, L"Use divahook.bat", L"Launches divahook.bat intead of diva.exe.", false, false),
new OptionMetaSeparator(), new OptionMetaSeparator(),
new OptionMetaSpacer(8), new OptionMetaSpacer(8),
new OptionMetaSectionLabel(L"Launcher"),
new BooleanOption(L"dark_launcher", LAUNCHER_SECTION, CONFIG_FILE, L"Dark Launcher", L"Sets the dark colour scheme in the launcher.", false, false), new BooleanOption(L"dark_launcher", LAUNCHER_SECTION, CONFIG_FILE, L"Dark Launcher", L"Sets the dark colour scheme in the launcher.", false, false),
new BooleanOption(L"acrylic_blur", LAUNCHER_SECTION, CONFIG_FILE, L"Acrylic Blur", L"Enables acrylic blur in the launcher on Windows 10 20H2 or later.", false, false), new BooleanOption(L"acrylic_blur", LAUNCHER_SECTION, CONFIG_FILE, L"Acrylic Blur", L"Enables acrylic blur in the launcher on Windows 10 20H2 or later.", false, false),
new BooleanOption(L"no_gpu_dialog", LAUNCHER_SECTION, CONFIG_FILE, L"Disable GPU Warning", L"Disables the warning dialog for unsupported GPUs.", false, false), new BooleanOption(L"no_gpu_dialog", LAUNCHER_SECTION, CONFIG_FILE, L"Disable GPU Warning", L"Disables the warning dialog for unsupported GPUs.", false, false),
//new BooleanOption(L"ignore_exe_checksum", PATCHES_SECTION, CONFIG_FILE, L"Ignore exe checksum", L"Use at your own risk.", false, false),
new StringOption(L"command_line", LAUNCHER_SECTION, CONFIG_FILE, L"Command Line:", L"Allows setting command line parameters for the game when using the launcher.\nDisabling the launcher will bypass this.", L"", false),
new BooleanOption(L"use_divahook_bat", LAUNCHER_SECTION, CONFIG_FILE, L"Use divahook.bat/start.bat", L"Launches divahook.bat/start.bat intead of diva.exe.", false, false),
}; };
ConfigOptionBase* playerdataArray[] = { ConfigOptionBase* playerdataArray[] = {
@@ -265,7 +277,7 @@ ConfigOptionBase* playerdataArray[] = {
new NumericOption(L"level_plate_id", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Level Plate:", L"Sets the level background image (plate).", 0, 0, INT_MAX), new NumericOption(L"level_plate_id", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Level Plate:", L"Sets the level background image (plate).", 0, 0, INT_MAX),
new NumericOption(L"level_plate_effect", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Level Plate Effect:", L"Sets the effect on the level background image (plate).", -1, -1, 2), new NumericOption(L"level_plate_effect", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Level Plate Effect:", L"Sets the effect on the level background image (plate).", -1, -1, 2),
new NumericOption(L"skin_equip ", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Skin:", L"Sets the gameplay UI skin.", 0, 0, INT_MAX), new NumericOption(L"skin_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Skin:", L"Sets the gameplay UI skin.", 0, 0, INT_MAX),
new NumericOption(L"btn_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Button Sound:", L"Sets the sound effect for buttons.\n-1 = song default", -1, -1, INT_MAX), new NumericOption(L"btn_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Button Sound:", L"Sets the sound effect for buttons.\n-1 = song default", -1, -1, INT_MAX),
new NumericOption(L"slide_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Slide Sound:", L"Sets the sound effect for slides.\n-1 = song default", -1, -1, INT_MAX), new NumericOption(L"slide_se_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Slide Sound:", L"Sets the sound effect for slides.\n-1 = song default", -1, -1, INT_MAX),
@@ -277,11 +289,11 @@ ConfigOptionBase* playerdataArray[] = {
new BooleanOption(L"border_excellent", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Excellent)", L"Shows the clear border for an excellent rating on the progress bar.", true, true), new BooleanOption(L"border_excellent", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Excellent)", L"Shows the clear border for an excellent rating on the progress bar.", true, true),
new BooleanOption(L"border_rival", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Rival)", L"Shows the clear border for beating your rival on the progress bar.", false, true), new BooleanOption(L"border_rival", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Clear Border (Rival)", L"Shows the clear border for beating your rival on the progress bar.", false, true),
new BooleanOption(L"use_card", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Use Card", L"Enables IC card. This allows module selection.", false, true), new BooleanOption(L"use_card", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Use Card", L"Enables IC card. This allows module selection.", true, true),
new BooleanOption(L"module_card_workaround", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Module Selection Workaround", L"Allows module selection without card and tries to improve menu performance.\n(BETA)", true, true), new BooleanOption(L"module_card_workaround", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Fast Module Selection (buggy)", L"Allows module selection without card and tries to improve menu performance.\nKnown to cause issues, especially with song-specific modules.", false, true),
new BooleanOption(L"use_pv_module_equip ", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Modules", L"Allows song-specific module selection.", false, true), new BooleanOption(L"use_pv_module_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Modules", L"Allows song-specific module selection.", true, true),
new BooleanOption(L"use_pv_skin_equip ", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Skins", L"Allows song-specific skin settings.\nValues stored in skins.ini", false, true), new BooleanOption(L"use_pv_skin_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Skins", L"Allows song-specific skin settings.\nValues stored in skins.ini", true, true),
new BooleanOption(L"use_pv_sfx_equip ", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Sound Effects", L"Allows song-specific sound effect settings.\nValues stored in sfx.ini", false, true), new BooleanOption(L"use_pv_sfx_equip", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Song Specific Sound Effects", L"Allows song-specific sound effect settings.\nValues stored in sfx.ini", true, true),
new BooleanOption(L"gamemode_options", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Game Modifiers", L"Allows use of game mode modifiers (hi-speed, hidden, and sudden).", true, true), new BooleanOption(L"gamemode_options", PLAYERDATA_SECTION, PLAYERDATA_FILE, L"Game Modifiers", L"Allows use of game mode modifiers (hi-speed, hidden, and sudden).", true, true),
}; };
@@ -399,6 +411,8 @@ std::vector<PluginInfo> LoadPlugins()
do { do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{ {
if (ffd.cFileName[0] == '.' && ffd.cFileName[1] == '_') continue; // exclude macOS metadata
auto pos = wcslen(ffd.cFileName); auto pos = wcslen(ffd.cFileName);
if (ffd.cFileName[pos - 4] == '.' && if (ffd.cFileName[pos - 4] == '.' &&
@@ -475,11 +489,13 @@ std::vector<PluginInfo> LoadCustom()
HANDLE hFind; HANDLE hFind;
WIN32_FIND_DATAW ffd; WIN32_FIND_DATAW ffd;
hFind = FindFirstFileW((PATCHES_DIR + L"\\*.p?").c_str(), &ffd); hFind = FindFirstFileW((PATCHES_DIR + L"\\*.p*").c_str(), &ffd);
if (hFind != INVALID_HANDLE_VALUE) { if (hFind != INVALID_HANDLE_VALUE) {
do { do {
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{ {
if (ffd.cFileName[0] == '.' && ffd.cFileName[1] == '_') continue; // exclude macOS metadata
auto pos = wcslen(ffd.cFileName); auto pos = wcslen(ffd.cFileName);
if ((ffd.cFileName[pos - 2] == '.' && (ffd.cFileName[pos - 1] == 'p' || ffd.cFileName[pos - 1] == 'P')) || if ((ffd.cFileName[pos - 2] == '.' && (ffd.cFileName[pos - 1] == 'p' || ffd.cFileName[pos - 1] == 'P')) ||
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

+278 -102
View File
@@ -10,6 +10,7 @@
#include "GPUModel.h" #include "GPUModel.h"
#include "WineVer.h" #include "WineVer.h"
#include "composition.h" #include "composition.h"
#include <filesystem>
namespace Launcher { namespace Launcher {
@@ -198,17 +199,32 @@ namespace Launcher {
vendor = vendor->Replace(" Corporation", ""); // this is useless.. remove it to help ensure the GPU type line fits vendor = vendor->Replace(" Corporation", ""); // this is useless.. remove it to help ensure the GPU type line fits
String^ renderer = gcnew String((char*)glGetString(GL_RENDERER)); String^ renderer = gcnew String((char*)glGetString(GL_RENDERER));
String^ version = gcnew String((char*)glGetString(GL_VERSION)); String^ version = gcnew String((char*)glGetString(GL_VERSION));
version = version->Replace(" Profile Context", ""); // we don't need this, either
String^ gpuModel = gcnew String(GPUModel::getGpuName().c_str()); String^ gpuModel = gcnew String(GPUModel::getGpuName().c_str());
String^ wineVersion = gcnew String(WineVer::getWineVer().c_str()); String^ wineVersion = gcnew String(WineVer::getWineVer().c_str());
int driver_version_major = 1;
int driver_version_minor = 0;
auto version_split = version->Split(' ');
if (version_split->Length > 1) // make sure we don't use the OpenGL version instead of the driver version
{
String^ driver_version = gcnew String(version_split[version_split->Length - 1]);
auto driver_version_split_major_minor = driver_version->Split('.');
if (driver_version_split_major_minor->Length >= 2)
{
driver_version_major = int::Parse(driver_version_split_major_minor[0]);
driver_version_minor = int::Parse(driver_version_split_major_minor[1]);
}
}
glutDestroyWindow(window); // destroy the window so it doesn't remain on screen glutDestroyWindow(window); // destroy the window so it doesn't remain on screen
if (glutMainLoopEventDynamic != NULL) glutMainLoopEventDynamic(); // freeglut needs this if (glutMainLoopEventDynamic != NULL) glutMainLoopEventDynamic(); // freeglut needs this
if (wineVersion != "") if (wineVersion != "")
{ {
this->labelGPU->Text = "Wine " + wineVersion + " (at least 4.12.1 is required)\n"; this->labelGPU->Text = "Wine " + wineVersion + " (remember to disable movies!)\n";
} }
else this->labelGPU->Text = "GPU Info:\n"; else this->labelGPU->Text = "GPU Info:\n";
this->labelGPU->Text += vendor + " " + renderer + "\n"; this->labelGPU->Text += vendor + " " + renderer + "\n";
@@ -226,11 +242,21 @@ namespace Launcher {
} }
if (hasNovidia) if (hasNovidia)
{
if (wineVersion == "" && (driver_version_major < 21 || (driver_version_major == 21 && driver_version_minor < 6)))
{
this->labelGPU->Text += L"Driver has known issues.";
GPUIssueText = L"The graphics driver you're using has known issues. Please install the latest driver from your GPU vendor's website.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
showGpuDialog = true;
}
else
{ {
this->labelGPU->Text += "Issues: AMD GPU support is unofficial."; this->labelGPU->Text += "Issues: AMD GPU support is unofficial.";
GPUIssueText = "AMD GPUs are not supported without mods.\nThe PD Loader AMDPack seems to be installed, but please keep in mind that it may have issues."; GPUIssueText = "AMD GPUs are not supported without mods.\nThe PD Loader AMDPack seems to be installed, but please keep in mind that it may have issues.";
this->labelGPU->LinkColor = System::Drawing::Color::Yellow; this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
} }
}
else else
{ {
this->labelGPU->Text += "Issues: Mods needed for AMD compatibility!"; this->labelGPU->Text += "Issues: Mods needed for AMD compatibility!";
@@ -239,71 +265,81 @@ namespace Launcher {
showGpuDialog = true; showGpuDialog = true;
} }
} }
else if (!vendor->Contains("NVIDIA")) else if (vendor->Contains("NVIDIA"))
{ {
this->labelGPU->Text += "Issues: UNSUPPORTED GPU!"; if (wineVersion == "" && (driver_version_major < 391 || (driver_version_major > 446 && driver_version_major < 460)))
GPUIssueText = "Your graphics card is not supported. Only NVIDIA GPUs are recommended. (though AMD ones can be used with mods)\nPlease use a GTX 600 series or later NVIDIA GPU.\n\nIf you have a laptop with an NVIDIA GPU and wish to use it instead of the detected GPU, you may need to set diva.exe to use it in Windows settings or NVIDIA Control Panel.\n\nOwners of other GPUs may be able to run the game using plugins or mods, but 3D graphics will probably not work."; {
this->labelGPU->LinkColor = System::Drawing::Color::Red; this->labelGPU->Text += L"Driver has known issues.";
GPUIssueText = L"The graphics driver you're using has known issues. Please install the latest driver from your GPU vendor's website.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
showGpuDialog = true; showGpuDialog = true;
} }
else if (gpuModel->StartsWith("GA")) // unconfirmed?? else if (gpuModel->StartsWith("GA")) // unconfirmed??
{ {
this->labelGPU->Text += "Issues: Ampere GPU detected! Unknown issues.\n(Click for more information)"; this->labelGPU->Text += L"Issues: Ampere GPU detected! Possible noise.\n(Click for more information)";
GPUIssueText = "Ampere GPUs have not been tested yet. On the previous generation Turing GPUs (GTX 16xx/RTX 20xx), some important character shaders have issues resulting in lines/noise.\nPlease make sure the ShaderPatch plugin is enabled and report any further issues to the developers."; 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; this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
} }
else if (gpuModel->StartsWith("TU")) else if (gpuModel->StartsWith("TU") || gpuModel->StartsWith("GV")) // let's assume Volta is like Turing for now
{ {
this->labelGPU->Text += "Issues: Turing GPU detected! Possible noise.\n(Click for more information)"; this->labelGPU->Text += L"Issues: Ampere GPU detected! Possible noise.\n(Click for more information)";
GPUIssueText = "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."; 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; this->labelGPU->LinkColor = System::Drawing::Color::Yellow;
} }
else if (gpuModel->StartsWith("GM") || gpuModel->StartsWith("GP") || gpuModel->StartsWith("GV")) else if (gpuModel->StartsWith("GM") || gpuModel->StartsWith("GP"))
{ {
this->labelGPU->Text += "Issues: May have minor noise on some stages.\n(Click for more information)"; this->labelGPU->Text += L"Issues: May have minor noise on some stages.\n(Click for more information)";
GPUIssueText = "On Maxwell GPUs (~GTX 900) or newer, some minor stage shaders create noise.\nPlease make sure the ShaderPatch plugin is enabled."; GPUIssueText = L"On Maxwell GPUs (~GTX 900) and newer, some minor stage shaders create noise.\nPlease make sure the ShaderPatch plugin is enabled.";
this->labelGPU->LinkColor = System::Drawing::Color::Teal; this->labelGPU->LinkColor = System::Drawing::Color::Teal;
} }
else if (gpuModel->StartsWith("GK")) else if (gpuModel->StartsWith("GK"))
{ {
this->labelGPU->Text += "Issues: None."; this->labelGPU->Text += L"Issues: None.";
GPUIssueText = "Your GPU should have no issues running the game."; GPUIssueText = L"Your GPU should have no issues running the game.";
this->labelGPU->LinkColor = System::Drawing::Color::LightBlue; this->labelGPU->LinkColor = System::Drawing::Color::LightBlue;
} }
else if (gpuModel->StartsWith("GF")) else if (gpuModel->StartsWith("GF"))
{ {
if (version[0] < '4') if (version[0] < '4')
{ {
this->labelGPU->Text += "Issues: Driver too old."; this->labelGPU->Text += L"Issues: Driver too old.";
GPUIssueText = "Your GPU should be able to run the game, but it looks like your OpenGL version is too old.\nA driver update should fix this."; GPUIssueText = L"Your GPU should be able to run the game, but it looks like your OpenGL version is too old.\nA driver update should fix this.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange; this->labelGPU->LinkColor = System::Drawing::Color::Orange;
showGpuDialog = true; showGpuDialog = true;
} }
else else
{ {
this->labelGPU->Text += "Issues: No known issues."; this->labelGPU->Text += L"Issues: No known issues.";
GPUIssueText = "Your GPU should have no issues running the game, but it is older than the GPU the game was originally designed for (GTX 650 Ti).\nThere may be some issues with graphics.\nPlease report any issues so that they can be analysed and potentially fixed."; GPUIssueText = L"Your GPU should have no issues running the game, but it is older than the GPU the game was originally designed for (GTX 650 Ti).\nThere may be some issues with graphics.\nPlease report any issues so that they can be analysed and potentially fixed.";
this->labelGPU->LinkColor = System::Drawing::Color::Teal; this->labelGPU->LinkColor = System::Drawing::Color::Teal;
} }
} }
else if (version[0] >= '4' && gpuModel->Length > 0 && !gpuModel->StartsWith("Unk") && !gpuModel->StartsWith("Oth"))
{
this->labelGPU->Text += "Issues: GPU may be too new.\n(Click for more information)";
GPUIssueText = "It looks like your GPU may be too new. Only up to Turing (GTX 16xx/RTX 20xx) is currently supported.\nGood news: the game should be capable of running, but shader patches (probably needed) may not support it yet.\nYou will likely see lines/noise on important character shaders and some minor stage shaders.\nPlease report any issues so that ShaderPatch can be updated.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
}
else if (gpuModel->StartsWith("G") || gpuModel->StartsWith("NV") || gpuModel->StartsWith("NB") || gpuModel->StartsWith("N10") || gpuModel->StartsWith("MCP")) else if (gpuModel->StartsWith("G") || gpuModel->StartsWith("NV") || gpuModel->StartsWith("NB") || gpuModel->StartsWith("N10") || gpuModel->StartsWith("MCP"))
{ {
this->labelGPU->Text += "Issues: GPU too old! 3D rendering might be broken.\n(Click for more information)"; this->labelGPU->Text += L"Issues: GPU too old! 3D rendering might be broken.\n(Click for more information)";
GPUIssueText = "Your GPU is very old and does not support rendering techniques used by the game.\nYou may be able to play, but graphics will likely have major issues.\nPlease upgrade to a GTX 600 series or later GPU."; GPUIssueText = L"Your GPU is very old and does not support rendering techniques used by the game.\nYou may be able to play, but graphics will likely have major issues.\nPlease upgrade to a GTX 600 series or later GPU.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange; this->labelGPU->LinkColor = System::Drawing::Color::Orange;
showGpuDialog = true; showGpuDialog = true;
} }
else if (version[0] >= '4' && gpuModel->Length > 0 && !gpuModel->StartsWith("Unk") && !gpuModel->StartsWith("Oth"))
{
this->labelGPU->Text += L"Issues: GPU may be too new.\n(Click for more information)";
GPUIssueText = L"It looks like your GPU may be too new. Only up to Ampere (RTX 30xx) is currently supported.\nGood news: the game should be capable of running, but shader patches (probably needed) may not support it yet.\nYou will likely see lines/noise on important character shaders and some minor stage shaders.\nPlease report any issues so that ShaderPatch can be updated.\nYou can also try forcing a specific GPU workaround type.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
}
else
{
this->labelGPU->Text += L"Issues: Unable to detect GPU architecture.\n(Click for more information)";
GPUIssueText = L"It looks like you have an NVIDIA GPU, but something went wrong while trying to determine your GPU's architecture (type).\nThis may be a caused by a bug, but it probably indicates potential issues.\nPlease make sure you have a GTX 600 series or later GPU. (GTX 400 series or later should also work)";
this->labelGPU->LinkColor = System::Drawing::Color::Orange;
showGpuDialog = true;
}
}
else //if (gpuModel->Length == 0 || gpuModel->StartsWith("Unk") || gpuModel->StartsWith("Oth")) else //if (gpuModel->Length == 0 || gpuModel->StartsWith("Unk") || gpuModel->StartsWith("Oth"))
{ {
this->labelGPU->Text += "Issues: Unable to detect GPU architecture.\n(Click for more information)"; this->labelGPU->Text += L"Issues: UNSUPPORTED GPU!";
GPUIssueText = "It looks like you have an NVIDIA GPU, but something went wrong while trying to determine your GPU's architecture (type).\nThis may be a caused by a bug, but it probably indicates potential issues.\nPlease make sure you have a GTX 600 series or later GPU. (GTX 400 series or later should also work)"; GPUIssueText = L"Your graphics card is not supported. Only NVIDIA GPUs are recommended (though AMD ones can be used with mods).\nPlease use a GTX 600 series or later NVIDIA GPU.\n\nIf you have a laptop with an NVIDIA GPU and wish to use it instead of the detected GPU, you may need to set diva.exe to use it in Windows settings or NVIDIA Control Panel.\n\nOwners of other GPUs may be able to run the game using plugins or mods, but 3D graphics will probably not work.";
this->labelGPU->LinkColor = System::Drawing::Color::Orange; this->labelGPU->LinkColor = System::Drawing::Color::Red;
showGpuDialog = true; showGpuDialog = true;
} }
int linkEnd = this->labelGPU->Text->Length - linkStart; int linkEnd = this->labelGPU->Text->Length - linkStart;
@@ -344,7 +380,7 @@ namespace Launcher {
void updateLagCompMsec() void updateLagCompMsec()
{ {
this->groupBox_Lag->Text = "Lag Compensation (" + this->trackBar_LagCompensation->Value * 10 + " msec)"; this->groupBox_Lag->Text = "Lag Compensation (" + this->trackBar_LagCompensation->Value + " msec)";
} }
void updateStyle() void updateStyle()
@@ -532,29 +568,45 @@ private: System::Windows::Forms::Button^ button_Wiki;
this->tabPage_Plugins->SuspendLayout(); this->tabPage_Plugins->SuspendLayout();
this->tabPage_Credits->SuspendLayout(); this->tabPage_Credits->SuspendLayout();
this->SuspendLayout(); this->SuspendLayout();
//
// button_Launch
//
this->button_Launch->BackColor = System::Drawing::Color::White; this->button_Launch->BackColor = System::Drawing::Color::White;
this->button_Launch->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control; this->button_Launch->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control;
this->button_Launch->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_Launch->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->button_Launch->Location = System::Drawing::Point(172, 389); this->button_Launch->Location = System::Drawing::Point(344, 778);
this->button_Launch->Margin = System::Windows::Forms::Padding(6);
this->button_Launch->Name = L"button_Launch"; this->button_Launch->Name = L"button_Launch";
this->button_Launch->Size = System::Drawing::Size(217, 23); this->button_Launch->Size = System::Drawing::Size(434, 46);
this->button_Launch->TabIndex = 20; this->button_Launch->TabIndex = 20;
this->button_Launch->Text = L"Launch"; this->button_Launch->Text = L"Launch";
this->button_Launch->UseVisualStyleBackColor = false; this->button_Launch->UseVisualStyleBackColor = false;
this->button_Launch->Click += gcnew System::EventHandler(this, &ui::Button_Launch_Click); this->button_Launch->Click += gcnew System::EventHandler(this, &ui::Button_Launch_Click);
//
// groupBox_ScreenRes
//
this->groupBox_ScreenRes->Controls->Add(this->panel_ScreenRes); this->groupBox_ScreenRes->Controls->Add(this->panel_ScreenRes);
this->groupBox_ScreenRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->groupBox_ScreenRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->groupBox_ScreenRes->Location = System::Drawing::Point(5, 6); this->groupBox_ScreenRes->Location = System::Drawing::Point(10, 12);
this->groupBox_ScreenRes->Margin = System::Windows::Forms::Padding(6);
this->groupBox_ScreenRes->Name = L"groupBox_ScreenRes"; this->groupBox_ScreenRes->Name = L"groupBox_ScreenRes";
this->groupBox_ScreenRes->Size = System::Drawing::Size(263, 113); this->groupBox_ScreenRes->Padding = System::Windows::Forms::Padding(6);
this->groupBox_ScreenRes->Size = System::Drawing::Size(526, 226);
this->groupBox_ScreenRes->TabIndex = 10; this->groupBox_ScreenRes->TabIndex = 10;
this->groupBox_ScreenRes->TabStop = false; this->groupBox_ScreenRes->TabStop = false;
this->groupBox_ScreenRes->Text = L"Screen Resolution"; this->groupBox_ScreenRes->Text = L"Screen Resolution";
//
// panel_ScreenRes
//
this->panel_ScreenRes->AutoScroll = true; this->panel_ScreenRes->AutoScroll = true;
this->panel_ScreenRes->Location = System::Drawing::Point(5, 19); this->panel_ScreenRes->Location = System::Drawing::Point(10, 38);
this->panel_ScreenRes->Margin = System::Windows::Forms::Padding(6);
this->panel_ScreenRes->Name = L"panel_ScreenRes"; this->panel_ScreenRes->Name = L"panel_ScreenRes";
this->panel_ScreenRes->Size = System::Drawing::Size(253, 89); this->panel_ScreenRes->Size = System::Drawing::Size(506, 178);
this->panel_ScreenRes->TabIndex = 0; this->panel_ScreenRes->TabIndex = 0;
//
// tabControl
//
this->tabControl->Controls->Add(this->tabPage_Resolution); this->tabControl->Controls->Add(this->tabPage_Resolution);
this->tabControl->Controls->Add(this->tabPage_Patches); this->tabControl->Controls->Add(this->tabPage_Patches);
this->tabControl->Controls->Add(this->tabPage_Playerdata); this->tabControl->Controls->Add(this->tabPage_Playerdata);
@@ -562,10 +614,14 @@ private: System::Windows::Forms::Button^ button_Wiki;
this->tabControl->Controls->Add(this->tabPage_Plugins); this->tabControl->Controls->Add(this->tabPage_Plugins);
this->tabControl->Controls->Add(this->tabPage_Credits); this->tabControl->Controls->Add(this->tabPage_Credits);
this->tabControl->Location = System::Drawing::Point(0, 0); this->tabControl->Location = System::Drawing::Point(0, 0);
this->tabControl->Margin = System::Windows::Forms::Padding(6);
this->tabControl->Name = L"tabControl"; this->tabControl->Name = L"tabControl";
this->tabControl->SelectedIndex = 0; this->tabControl->SelectedIndex = 0;
this->tabControl->Size = System::Drawing::Size(560, 384); this->tabControl->Size = System::Drawing::Size(1120, 768);
this->tabControl->TabIndex = 10; this->tabControl->TabIndex = 10;
//
// tabPage_Resolution
//
this->tabPage_Resolution->BackColor = System::Drawing::Color::White; this->tabPage_Resolution->BackColor = System::Drawing::Color::White;
this->tabPage_Resolution->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch; this->tabPage_Resolution->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch;
this->tabPage_Resolution->Controls->Add(this->groupBox_Lag); this->tabPage_Resolution->Controls->Add(this->groupBox_Lag);
@@ -575,181 +631,271 @@ private: System::Windows::Forms::Button^ button_Wiki;
this->tabPage_Resolution->Controls->Add(this->groupBox_ScreenRes); this->tabPage_Resolution->Controls->Add(this->groupBox_ScreenRes);
this->tabPage_Resolution->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), this->tabPage_Resolution->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Resolution->Location = System::Drawing::Point(4, 22); this->tabPage_Resolution->Location = System::Drawing::Point(8, 39);
this->tabPage_Resolution->Margin = System::Windows::Forms::Padding(6);
this->tabPage_Resolution->Name = L"tabPage_Resolution"; this->tabPage_Resolution->Name = L"tabPage_Resolution";
this->tabPage_Resolution->Padding = System::Windows::Forms::Padding(3); this->tabPage_Resolution->Padding = System::Windows::Forms::Padding(6);
this->tabPage_Resolution->Size = System::Drawing::Size(552, 358); this->tabPage_Resolution->Size = System::Drawing::Size(1104, 721);
this->tabPage_Resolution->TabIndex = 0; this->tabPage_Resolution->TabIndex = 0;
this->tabPage_Resolution->Text = L"Graphics"; this->tabPage_Resolution->Text = L"Graphics";
//
// groupBox_Lag
//
this->groupBox_Lag->Controls->Add(this->trackBar_LagCompensation); this->groupBox_Lag->Controls->Add(this->trackBar_LagCompensation);
this->groupBox_Lag->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->groupBox_Lag->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->groupBox_Lag->Location = System::Drawing::Point(5, 282); this->groupBox_Lag->Location = System::Drawing::Point(10, 564);
this->groupBox_Lag->Margin = System::Windows::Forms::Padding(6);
this->groupBox_Lag->Name = L"groupBox_Lag"; this->groupBox_Lag->Name = L"groupBox_Lag";
this->groupBox_Lag->Size = System::Drawing::Size(263, 70); this->groupBox_Lag->Padding = System::Windows::Forms::Padding(6);
this->groupBox_Lag->Size = System::Drawing::Size(526, 146);
this->groupBox_Lag->TabIndex = 21; this->groupBox_Lag->TabIndex = 21;
this->groupBox_Lag->TabStop = false; this->groupBox_Lag->TabStop = false;
this->groupBox_Lag->Text = L"Lag Compensation"; this->groupBox_Lag->Text = L"Lag Compensation";
this->trackBar_LagCompensation->Location = System::Drawing::Point(7, 20); //
this->trackBar_LagCompensation->Maximum = 50; // trackBar_LagCompensation
//
this->trackBar_LagCompensation->LargeChange = 1;
this->trackBar_LagCompensation->Location = System::Drawing::Point(14, 40);
this->trackBar_LagCompensation->Margin = System::Windows::Forms::Padding(6);
this->trackBar_LagCompensation->Maximum = 500;
this->trackBar_LagCompensation->Name = L"trackBar_LagCompensation"; this->trackBar_LagCompensation->Name = L"trackBar_LagCompensation";
this->trackBar_LagCompensation->Size = System::Drawing::Size(250, 45); this->trackBar_LagCompensation->Size = System::Drawing::Size(500, 90);
this->trackBar_LagCompensation->TabIndex = 0; this->trackBar_LagCompensation->TabIndex = 0;
this->trackBar_LagCompensation->TickStyle = System::Windows::Forms::TickStyle::None;
this->trackBar_LagCompensation->ValueChanged += gcnew System::EventHandler(this, &ui::trackBar_LagCompensation_ValueChanged); this->trackBar_LagCompensation->ValueChanged += gcnew System::EventHandler(this, &ui::trackBar_LagCompensation_ValueChanged);
//
// groupBox_Details
//
this->groupBox_Details->Controls->Add(this->panel_Details); this->groupBox_Details->Controls->Add(this->panel_Details);
this->groupBox_Details->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->groupBox_Details->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->groupBox_Details->Location = System::Drawing::Point(274, 6); this->groupBox_Details->Location = System::Drawing::Point(548, 12);
this->groupBox_Details->Margin = System::Windows::Forms::Padding(6);
this->groupBox_Details->Name = L"groupBox_Details"; this->groupBox_Details->Name = L"groupBox_Details";
this->groupBox_Details->Size = System::Drawing::Size(272, 346); this->groupBox_Details->Padding = System::Windows::Forms::Padding(6);
this->groupBox_Details->Size = System::Drawing::Size(544, 698);
this->groupBox_Details->TabIndex = 11; this->groupBox_Details->TabIndex = 11;
this->groupBox_Details->TabStop = false; this->groupBox_Details->TabStop = false;
this->groupBox_Details->Text = L"Details"; this->groupBox_Details->Text = L"Details";
//
// panel_Details
//
this->panel_Details->AutoScroll = true; this->panel_Details->AutoScroll = true;
this->panel_Details->Location = System::Drawing::Point(5, 19); this->panel_Details->Location = System::Drawing::Point(10, 23);
this->panel_Details->Margin = System::Windows::Forms::Padding(6);
this->panel_Details->Name = L"panel_Details"; this->panel_Details->Name = L"panel_Details";
this->panel_Details->Size = System::Drawing::Size(261, 321); this->panel_Details->Size = System::Drawing::Size(522, 667);
this->panel_Details->TabIndex = 0; this->panel_Details->TabIndex = 0;
//
// labelGPU
//
this->labelGPU->AutoSize = true; this->labelGPU->AutoSize = true;
this->labelGPU->BackColor = System::Drawing::Color::Transparent; this->labelGPU->BackColor = System::Drawing::Color::Transparent;
this->labelGPU->ForeColor = System::Drawing::Color::Black; this->labelGPU->ForeColor = System::Drawing::Color::Black;
this->labelGPU->Location = System::Drawing::Point(5, 209); this->labelGPU->Location = System::Drawing::Point(10, 418);
this->labelGPU->Margin = System::Windows::Forms::Padding(2, 0, 2, 0); this->labelGPU->Margin = System::Windows::Forms::Padding(4, 0, 4, 0);
this->labelGPU->MinimumSize = System::Drawing::Size(263, 13); this->labelGPU->MinimumSize = System::Drawing::Size(526, 26);
this->labelGPU->Name = L"labelGPU"; this->labelGPU->Name = L"labelGPU";
this->labelGPU->Size = System::Drawing::Size(263, 13); this->labelGPU->Size = System::Drawing::Size(526, 26);
this->labelGPU->TabIndex = 21; this->labelGPU->TabIndex = 21;
this->labelGPU->TextAlign = System::Drawing::ContentAlignment::MiddleLeft; this->labelGPU->TextAlign = System::Drawing::ContentAlignment::MiddleLeft;
//
// groupBox_InternalRes
//
this->groupBox_InternalRes->Controls->Add(this->panel_IntRes); this->groupBox_InternalRes->Controls->Add(this->panel_IntRes);
this->groupBox_InternalRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->groupBox_InternalRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->groupBox_InternalRes->Location = System::Drawing::Point(5, 124); this->groupBox_InternalRes->Location = System::Drawing::Point(10, 248);
this->groupBox_InternalRes->Margin = System::Windows::Forms::Padding(6);
this->groupBox_InternalRes->Name = L"groupBox_InternalRes"; this->groupBox_InternalRes->Name = L"groupBox_InternalRes";
this->groupBox_InternalRes->Size = System::Drawing::Size(263, 83); this->groupBox_InternalRes->Padding = System::Windows::Forms::Padding(6);
this->groupBox_InternalRes->Size = System::Drawing::Size(526, 166);
this->groupBox_InternalRes->TabIndex = 20; this->groupBox_InternalRes->TabIndex = 20;
this->groupBox_InternalRes->TabStop = false; this->groupBox_InternalRes->TabStop = false;
this->groupBox_InternalRes->Text = L"Internal Resolution (Quality)"; this->groupBox_InternalRes->Text = L"Internal Resolution (Quality)";
//
// panel_IntRes
//
this->panel_IntRes->AutoScroll = true; this->panel_IntRes->AutoScroll = true;
this->panel_IntRes->Location = System::Drawing::Point(5, 19); this->panel_IntRes->Location = System::Drawing::Point(10, 38);
this->panel_IntRes->Margin = System::Windows::Forms::Padding(6);
this->panel_IntRes->Name = L"panel_IntRes"; this->panel_IntRes->Name = L"panel_IntRes";
this->panel_IntRes->Size = System::Drawing::Size(253, 59); this->panel_IntRes->Size = System::Drawing::Size(506, 118);
this->panel_IntRes->TabIndex = 1; this->panel_IntRes->TabIndex = 1;
//
// tabPage_Patches
//
this->tabPage_Patches->BackColor = System::Drawing::Color::White; this->tabPage_Patches->BackColor = System::Drawing::Color::White;
this->tabPage_Patches->Controls->Add(this->panel_Patches); this->tabPage_Patches->Controls->Add(this->panel_Patches);
this->tabPage_Patches->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)), this->tabPage_Patches->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Patches->Location = System::Drawing::Point(4, 22); this->tabPage_Patches->Location = System::Drawing::Point(8, 39);
this->tabPage_Patches->Margin = System::Windows::Forms::Padding(6);
this->tabPage_Patches->Name = L"tabPage_Patches"; this->tabPage_Patches->Name = L"tabPage_Patches";
this->tabPage_Patches->Size = System::Drawing::Size(552, 358); this->tabPage_Patches->Size = System::Drawing::Size(1104, 721);
this->tabPage_Patches->TabIndex = 1; this->tabPage_Patches->TabIndex = 1;
this->tabPage_Patches->Text = L"Options"; this->tabPage_Patches->Text = L"Options";
//
// panel_Patches
//
this->panel_Patches->AutoScroll = true; this->panel_Patches->AutoScroll = true;
this->panel_Patches->Location = System::Drawing::Point(0, 0); this->panel_Patches->Location = System::Drawing::Point(0, 0);
this->panel_Patches->Margin = System::Windows::Forms::Padding(6);
this->panel_Patches->Name = L"panel_Patches"; this->panel_Patches->Name = L"panel_Patches";
this->panel_Patches->Size = System::Drawing::Size(552, 358); this->panel_Patches->Size = System::Drawing::Size(1104, 716);
this->panel_Patches->TabIndex = 9; this->panel_Patches->TabIndex = 9;
//
// tabPage_Playerdata
//
this->tabPage_Playerdata->BackColor = System::Drawing::Color::White; this->tabPage_Playerdata->BackColor = System::Drawing::Color::White;
this->tabPage_Playerdata->Controls->Add(this->panel_Playerdata); this->tabPage_Playerdata->Controls->Add(this->panel_Playerdata);
this->tabPage_Playerdata->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), this->tabPage_Playerdata->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Playerdata->Location = System::Drawing::Point(4, 22); this->tabPage_Playerdata->Location = System::Drawing::Point(8, 39);
this->tabPage_Playerdata->Margin = System::Windows::Forms::Padding(6);
this->tabPage_Playerdata->Name = L"tabPage_Playerdata"; this->tabPage_Playerdata->Name = L"tabPage_Playerdata";
this->tabPage_Playerdata->Size = System::Drawing::Size(552, 358); this->tabPage_Playerdata->Size = System::Drawing::Size(1104, 721);
this->tabPage_Playerdata->TabIndex = 3; this->tabPage_Playerdata->TabIndex = 3;
this->tabPage_Playerdata->Text = L"Player"; this->tabPage_Playerdata->Text = L"Player";
//
// panel_Playerdata
//
this->panel_Playerdata->AutoScroll = true; this->panel_Playerdata->AutoScroll = true;
this->panel_Playerdata->Location = System::Drawing::Point(0, 0); this->panel_Playerdata->Location = System::Drawing::Point(0, 0);
this->panel_Playerdata->Margin = System::Windows::Forms::Padding(6);
this->panel_Playerdata->Name = L"panel_Playerdata"; this->panel_Playerdata->Name = L"panel_Playerdata";
this->panel_Playerdata->Size = System::Drawing::Size(552, 358); this->panel_Playerdata->Size = System::Drawing::Size(1104, 716);
this->panel_Playerdata->TabIndex = 1; this->panel_Playerdata->TabIndex = 1;
//
// tabPage_Components
//
this->tabPage_Components->BackColor = System::Drawing::Color::White; this->tabPage_Components->BackColor = System::Drawing::Color::White;
this->tabPage_Components->Controls->Add(this->panel_Components); this->tabPage_Components->Controls->Add(this->panel_Components);
this->tabPage_Components->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), this->tabPage_Components->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Components->Location = System::Drawing::Point(4, 22); this->tabPage_Components->Location = System::Drawing::Point(8, 39);
this->tabPage_Components->Margin = System::Windows::Forms::Padding(6);
this->tabPage_Components->Name = L"tabPage_Components"; this->tabPage_Components->Name = L"tabPage_Components";
this->tabPage_Components->Padding = System::Windows::Forms::Padding(3); this->tabPage_Components->Padding = System::Windows::Forms::Padding(6);
this->tabPage_Components->Size = System::Drawing::Size(552, 358); this->tabPage_Components->Size = System::Drawing::Size(1104, 721);
this->tabPage_Components->TabIndex = 2; this->tabPage_Components->TabIndex = 2;
this->tabPage_Components->Text = L"Components"; this->tabPage_Components->Text = L"Components";
//
// panel_Components
//
this->panel_Components->AutoScroll = true; this->panel_Components->AutoScroll = true;
this->panel_Components->Location = System::Drawing::Point(0, 0); this->panel_Components->Location = System::Drawing::Point(0, 0);
this->panel_Components->Margin = System::Windows::Forms::Padding(6);
this->panel_Components->Name = L"panel_Components"; this->panel_Components->Name = L"panel_Components";
this->panel_Components->Size = System::Drawing::Size(552, 358); this->panel_Components->Size = System::Drawing::Size(1104, 716);
this->panel_Components->TabIndex = 0; this->panel_Components->TabIndex = 0;
//
// tabPage_Plugins
//
this->tabPage_Plugins->BackColor = System::Drawing::Color::White; this->tabPage_Plugins->BackColor = System::Drawing::Color::White;
this->tabPage_Plugins->Controls->Add(this->panel_Custom); this->tabPage_Plugins->Controls->Add(this->panel_Custom);
this->tabPage_Plugins->Controls->Add(this->panel_Plugins); this->tabPage_Plugins->Controls->Add(this->panel_Plugins);
this->tabPage_Plugins->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)), this->tabPage_Plugins->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->tabPage_Plugins->Location = System::Drawing::Point(4, 22); this->tabPage_Plugins->Location = System::Drawing::Point(8, 39);
this->tabPage_Plugins->Margin = System::Windows::Forms::Padding(6);
this->tabPage_Plugins->Name = L"tabPage_Plugins"; this->tabPage_Plugins->Name = L"tabPage_Plugins";
this->tabPage_Plugins->Padding = System::Windows::Forms::Padding(3); this->tabPage_Plugins->Padding = System::Windows::Forms::Padding(6);
this->tabPage_Plugins->Size = System::Drawing::Size(552, 358); this->tabPage_Plugins->Size = System::Drawing::Size(1104, 721);
this->tabPage_Plugins->TabIndex = 3; this->tabPage_Plugins->TabIndex = 3;
this->tabPage_Plugins->Text = L"Plugins and Patches"; this->tabPage_Plugins->Text = L"Plugins and Patches";
//
// panel_Custom
//
this->panel_Custom->AutoScroll = true; this->panel_Custom->AutoScroll = true;
this->panel_Custom->Location = System::Drawing::Point(276, 0); this->panel_Custom->Location = System::Drawing::Point(552, 0);
this->panel_Custom->Margin = System::Windows::Forms::Padding(6);
this->panel_Custom->Name = L"panel_Custom"; this->panel_Custom->Name = L"panel_Custom";
this->panel_Custom->Size = System::Drawing::Size(276, 358); this->panel_Custom->Size = System::Drawing::Size(552, 716);
this->panel_Custom->TabIndex = 3; this->panel_Custom->TabIndex = 3;
//
// panel_Plugins
//
this->panel_Plugins->AutoScroll = true; this->panel_Plugins->AutoScroll = true;
this->panel_Plugins->Location = System::Drawing::Point(0, 0); this->panel_Plugins->Location = System::Drawing::Point(0, 0);
this->panel_Plugins->Margin = System::Windows::Forms::Padding(6);
this->panel_Plugins->Name = L"panel_Plugins"; this->panel_Plugins->Name = L"panel_Plugins";
this->panel_Plugins->Size = System::Drawing::Size(276, 358); this->panel_Plugins->Size = System::Drawing::Size(552, 716);
this->panel_Plugins->TabIndex = 0; this->panel_Plugins->TabIndex = 0;
//
// tabPage_Credits
//
this->tabPage_Credits->Controls->Add(this->creditsTextBox); this->tabPage_Credits->Controls->Add(this->creditsTextBox);
this->tabPage_Credits->Location = System::Drawing::Point(4, 22); this->tabPage_Credits->Location = System::Drawing::Point(8, 39);
this->tabPage_Credits->Margin = System::Windows::Forms::Padding(2); this->tabPage_Credits->Margin = System::Windows::Forms::Padding(4);
this->tabPage_Credits->Name = L"tabPage_Credits"; this->tabPage_Credits->Name = L"tabPage_Credits";
this->tabPage_Credits->Padding = System::Windows::Forms::Padding(2); this->tabPage_Credits->Padding = System::Windows::Forms::Padding(4);
this->tabPage_Credits->Size = System::Drawing::Size(552, 358); this->tabPage_Credits->Size = System::Drawing::Size(1104, 721);
this->tabPage_Credits->TabIndex = 5; this->tabPage_Credits->TabIndex = 5;
this->tabPage_Credits->Text = L"Credits"; this->tabPage_Credits->Text = L"Credits";
this->tabPage_Credits->UseVisualStyleBackColor = true; this->tabPage_Credits->UseVisualStyleBackColor = true;
//
// creditsTextBox
//
this->creditsTextBox->BackColor = System::Drawing::Color::White; this->creditsTextBox->BackColor = System::Drawing::Color::White;
this->creditsTextBox->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)), this->creditsTextBox->ForeColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(64)), static_cast<System::Int32>(static_cast<System::Byte>(64)),
static_cast<System::Int32>(static_cast<System::Byte>(64))); static_cast<System::Int32>(static_cast<System::Byte>(64)));
this->creditsTextBox->Location = System::Drawing::Point(0, 0); this->creditsTextBox->Location = System::Drawing::Point(0, 0);
this->creditsTextBox->Margin = System::Windows::Forms::Padding(2); this->creditsTextBox->Margin = System::Windows::Forms::Padding(4);
this->creditsTextBox->Multiline = true; this->creditsTextBox->Multiline = true;
this->creditsTextBox->Name = L"creditsTextBox"; this->creditsTextBox->Name = L"creditsTextBox";
this->creditsTextBox->ReadOnly = true; this->creditsTextBox->ReadOnly = true;
this->creditsTextBox->ScrollBars = System::Windows::Forms::ScrollBars::Both; this->creditsTextBox->ScrollBars = System::Windows::Forms::ScrollBars::Both;
this->creditsTextBox->Size = System::Drawing::Size(552, 358); this->creditsTextBox->Size = System::Drawing::Size(1100, 712);
this->creditsTextBox->TabIndex = 0; this->creditsTextBox->TabIndex = 0;
this->creditsTextBox->Text = resources->GetString(L"creditsTextBox.Text"); this->creditsTextBox->Text = resources->GetString(L"creditsTextBox.Text");
//
// button_Discord
//
this->button_Discord->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)), this->button_Discord->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)),
static_cast<System::Int32>(static_cast<System::Byte>(242))); static_cast<System::Int32>(static_cast<System::Byte>(242)));
this->button_Discord->Cursor = System::Windows::Forms::Cursors::Hand; this->button_Discord->Cursor = System::Windows::Forms::Cursors::Hand;
this->button_Discord->FlatAppearance->BorderSize = 0; this->button_Discord->FlatAppearance->BorderSize = 0;
this->button_Discord->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_Discord->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->button_Discord->Image = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_Discord.Image"))); this->button_Discord->Image = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_Discord.Image")));
this->button_Discord->Location = System::Drawing::Point(496, 384); this->button_Discord->Location = System::Drawing::Point(992, 768);
this->button_Discord->Margin = System::Windows::Forms::Padding(6);
this->button_Discord->Name = L"button_Discord"; this->button_Discord->Name = L"button_Discord";
this->button_Discord->Size = System::Drawing::Size(32, 32); this->button_Discord->Size = System::Drawing::Size(64, 64);
this->button_Discord->TabIndex = 31; this->button_Discord->TabIndex = 31;
this->button_Discord->UseVisualStyleBackColor = false; this->button_Discord->UseVisualStyleBackColor = false;
this->button_Discord->Click += gcnew System::EventHandler(this, &ui::button_Discord_Click); this->button_Discord->Click += gcnew System::EventHandler(this, &ui::button_Discord_Click);
//
// button_github
//
this->button_github->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)), this->button_github->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)),
static_cast<System::Int32>(static_cast<System::Byte>(242))); static_cast<System::Int32>(static_cast<System::Byte>(242)));
this->button_github->Cursor = System::Windows::Forms::Cursors::Hand; this->button_github->Cursor = System::Windows::Forms::Cursors::Hand;
this->button_github->FlatAppearance->BorderSize = 0; this->button_github->FlatAppearance->BorderSize = 0;
this->button_github->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_github->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->button_github->Image = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_github.Image"))); this->button_github->Image = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_github.Image")));
this->button_github->Location = System::Drawing::Point(528, 384); this->button_github->Location = System::Drawing::Point(1056, 768);
this->button_github->Margin = System::Windows::Forms::Padding(6);
this->button_github->Name = L"button_github"; this->button_github->Name = L"button_github";
this->button_github->Size = System::Drawing::Size(32, 32); this->button_github->Size = System::Drawing::Size(64, 64);
this->button_github->TabIndex = 32; this->button_github->TabIndex = 32;
this->button_github->UseVisualStyleBackColor = false; this->button_github->UseVisualStyleBackColor = false;
this->button_github->Click += gcnew System::EventHandler(this, &ui::button_github_Click); this->button_github->Click += gcnew System::EventHandler(this, &ui::button_github_Click);
//
// button_Apply
//
this->button_Apply->BackColor = System::Drawing::Color::White; this->button_Apply->BackColor = System::Drawing::Color::White;
this->button_Apply->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control; this->button_Apply->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control;
this->button_Apply->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_Apply->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->button_Apply->Location = System::Drawing::Point(4, 389); this->button_Apply->Location = System::Drawing::Point(8, 778);
this->button_Apply->Margin = System::Windows::Forms::Padding(6);
this->button_Apply->Name = L"button_Apply"; this->button_Apply->Name = L"button_Apply";
this->button_Apply->Size = System::Drawing::Size(69, 23); this->button_Apply->Size = System::Drawing::Size(138, 46);
this->button_Apply->TabIndex = 33; this->button_Apply->TabIndex = 33;
this->button_Apply->Text = L"Apply"; this->button_Apply->Text = L"Apply";
this->button_Apply->UseVisualStyleBackColor = false; this->button_Apply->UseVisualStyleBackColor = false;
this->button_Apply->Click += gcnew System::EventHandler(this, &ui::button_Apply_Click); this->button_Apply->Click += gcnew System::EventHandler(this, &ui::button_Apply_Click);
//
// button_Wiki
//
this->button_Wiki->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)), this->button_Wiki->BackColor = System::Drawing::Color::FromArgb(static_cast<System::Int32>(static_cast<System::Byte>(242)), static_cast<System::Int32>(static_cast<System::Byte>(242)),
static_cast<System::Int32>(static_cast<System::Byte>(242))); static_cast<System::Int32>(static_cast<System::Byte>(242)));
this->button_Wiki->BackgroundImage = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_Wiki.BackgroundImage"))); this->button_Wiki->BackgroundImage = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"button_Wiki.BackgroundImage")));
@@ -757,20 +903,24 @@ private: System::Windows::Forms::Button^ button_Wiki;
this->button_Wiki->Cursor = System::Windows::Forms::Cursors::Hand; this->button_Wiki->Cursor = System::Windows::Forms::Cursors::Hand;
this->button_Wiki->FlatAppearance->BorderSize = 0; this->button_Wiki->FlatAppearance->BorderSize = 0;
this->button_Wiki->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_Wiki->FlatStyle = System::Windows::Forms::FlatStyle::Flat;
this->button_Wiki->Location = System::Drawing::Point(464, 384); this->button_Wiki->Location = System::Drawing::Point(928, 768);
this->button_Wiki->Margin = System::Windows::Forms::Padding(6);
this->button_Wiki->Name = L"button_Wiki"; this->button_Wiki->Name = L"button_Wiki";
this->button_Wiki->Size = System::Drawing::Size(32, 32); this->button_Wiki->Size = System::Drawing::Size(64, 64);
this->button_Wiki->TabIndex = 34; this->button_Wiki->TabIndex = 34;
this->button_Wiki->UseVisualStyleBackColor = false; this->button_Wiki->UseVisualStyleBackColor = false;
this->button_Wiki->Click += gcnew System::EventHandler(this, &ui::button_Wiki_Click); this->button_Wiki->Click += gcnew System::EventHandler(this, &ui::button_Wiki_Click);
//
// ui
//
this->AcceptButton = this->button_Launch; this->AcceptButton = this->button_Launch;
this->AutoScaleDimensions = System::Drawing::SizeF(96, 96); this->AutoScaleDimensions = System::Drawing::SizeF(192, 192);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Dpi; this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Dpi;
this->AutoSize = true; this->AutoSize = true;
this->AutoSizeMode = System::Windows::Forms::AutoSizeMode::GrowAndShrink; this->AutoSizeMode = System::Windows::Forms::AutoSizeMode::GrowAndShrink;
this->BackColor = System::Drawing::Color::Magenta; this->BackColor = System::Drawing::Color::Magenta;
this->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch; this->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch;
this->ClientSize = System::Drawing::Size(560, 417); this->ClientSize = System::Drawing::Size(1120, 834);
this->Controls->Add(this->button_Wiki); this->Controls->Add(this->button_Wiki);
this->Controls->Add(this->button_Apply); this->Controls->Add(this->button_Apply);
this->Controls->Add(this->tabControl); this->Controls->Add(this->tabControl);
@@ -784,10 +934,11 @@ private: System::Windows::Forms::Button^ button_Wiki;
this->HelpButton = true; this->HelpButton = true;
this->Icon = (cli::safe_cast<System::Drawing::Icon^>(resources->GetObject(L"$this.Icon"))); this->Icon = (cli::safe_cast<System::Drawing::Icon^>(resources->GetObject(L"$this.Icon")));
this->KeyPreview = true; this->KeyPreview = true;
this->Margin = System::Windows::Forms::Padding(6);
this->MaximizeBox = false; this->MaximizeBox = false;
this->Name = L"ui"; this->Name = L"ui";
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen; this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Text = L"PD Launcher"; this->Text = L"PD Launcher (2.6.5a)";
this->TransparencyKey = System::Drawing::Color::Magenta; this->TransparencyKey = System::Drawing::Color::Magenta;
this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &ui::Ui_FormClosing); this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &ui::Ui_FormClosing);
this->FormClosed += gcnew System::Windows::Forms::FormClosedEventHandler(this, &ui::Ui_FormClosed); this->FormClosed += gcnew System::Windows::Forms::FormClosedEventHandler(this, &ui::Ui_FormClosed);
@@ -888,7 +1039,7 @@ private: System::Void SaveSettings() {
} }
} }
private: System::Void Button_Help_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void Button_Help_Click(System::Object^ sender, System::EventArgs^ e) {
System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader/wiki"); System::Diagnostics::Process::Start("https://github.com/PDModdingCommunity/PD-Loader/wiki");
} }
private: System::Void Button_Launch_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void Button_Launch_Click(System::Object^ sender, System::EventArgs^ e) {
@@ -896,13 +1047,38 @@ private: System::Void Button_Launch_Click(System::Object^ sender, System::EventA
SaveSettings(); SaveSettings();
if(GetPrivateProfileIntW(LAUNCHER_SECTION, L"use_divahook_bat", FALSE, CONFIG_FILE)) if (GetPrivateProfileIntW(LAUNCHER_SECTION, L"use_divahook_bat", FALSE, CONFIG_FILE))
{ {
if (GetPrivateProfileIntW(L"patches", L"quick_start", 1, CONFIG_FILE) > 0)
{
SkinnedMessageBox::Show(this, L"\"Quick Start\" and \"Use divahook.bat / start.bat\" cannot be enabled at the same time.", "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Error);
return;
}
DIVA_EXECUTABLE = NULL; DIVA_EXECUTABLE = NULL;
wstring DIVA_EXECUTABLE_LAUNCH_STRING = L"cmd.exe /C \""; wstring DIVA_EXECUTABLE_LAUNCH_STRING_cmd = L"cmd.exe /C \"";
DIVA_EXECUTABLE_LAUNCH_STRING.append(DIVA_DIRPATH); const wstring DIVA_EXECUTABLE_LAUNCH_STRING_path = DIVA_DIRPATH;
DIVA_EXECUTABLE_LAUNCH_STRING.append(L"\\divahook.bat\"");
DIVA_EXECUTABLE_LAUNCH = const_cast<WCHAR*>(DIVA_EXECUTABLE_LAUNCH_STRING.c_str()); wstring DIVAHOOK_BAT_PATH = DIVA_EXECUTABLE_LAUNCH_STRING_path;
DIVAHOOK_BAT_PATH.append(L"\\divahook.bat");
if (std::filesystem::exists(DIVAHOOK_BAT_PATH))
{
DIVA_EXECUTABLE_LAUNCH_STRING_cmd.append(DIVAHOOK_BAT_PATH);
DIVA_EXECUTABLE_LAUNCH_STRING_cmd.append(L"\"");
DIVA_EXECUTABLE_LAUNCH = const_cast<WCHAR*>(DIVA_EXECUTABLE_LAUNCH_STRING_cmd.c_str());
}
else
{
wstring START_BAT_PATH = DIVA_EXECUTABLE_LAUNCH_STRING_path;
START_BAT_PATH.append(L"\\start.bat");
if (std::filesystem::exists(START_BAT_PATH))
{
DIVA_EXECUTABLE_LAUNCH_STRING_cmd.append(START_BAT_PATH);
DIVA_EXECUTABLE_LAUNCH_STRING_cmd.append(L"\"");
DIVA_EXECUTABLE_LAUNCH = const_cast<WCHAR*>(DIVA_EXECUTABLE_LAUNCH_STRING_cmd.c_str());
}
else if (SkinnedMessageBox::Show(this, L"divahook.bat/start.bat not found.\nThe game will start normally/offline.\n\nNOTE: Disable \"Use divahook.bat / start.bat\" to avoid this warning.", "PD Launcher", MessageBoxButtons::OKCancel, MessageBoxIcon::Warning) != System::Windows::Forms::DialogResult::OK) return;
}
} }
else else
{ {
@@ -942,7 +1118,7 @@ private: System::Void DisplayTypeChangedHandler(System::Object^ sender, System::
{ {
for (ConfigOptionBase* option : screenResolutionArray) for (ConfigOptionBase* option : screenResolutionArray)
{ {
if (option != DisplayModeDropdown && option != DisplayResolutionOption) if (option == RefreshRateOption)
{ {
((Control^)Control::FromHandle(option->mainControlHandle))->Enabled = true; ((Control^)Control::FromHandle(option->mainControlHandle))->Enabled = true;
} }
@@ -952,7 +1128,7 @@ private: System::Void DisplayTypeChangedHandler(System::Object^ sender, System::
{ {
for (ConfigOptionBase* option : screenResolutionArray) for (ConfigOptionBase* option : screenResolutionArray)
{ {
if (option != DisplayModeDropdown && option != DisplayResolutionOption) if (option == RefreshRateOption)
{ {
((Control^)Control::FromHandle(option->mainControlHandle))->Enabled = false; ((Control^)Control::FromHandle(option->mainControlHandle))->Enabled = false;
} }
@@ -985,7 +1161,7 @@ private: System::Void button_Discord_Click(System::Object^ sender, System::Event
switch (SkinnedMessageBox::Show(this, "Would you like to read the user guide for troubleshooting?", "PD Launcher", MessageBoxButtons::YesNoCancel, MessageBoxIcon::Information)) switch (SkinnedMessageBox::Show(this, "Would you like to read the user guide for troubleshooting?", "PD Launcher", MessageBoxButtons::YesNoCancel, MessageBoxIcon::Information))
{ {
case System::Windows::Forms::DialogResult::Yes: case System::Windows::Forms::DialogResult::Yes:
System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader/wiki"); System::Diagnostics::Process::Start("https://github.com/PDModdingCommunity/PD-Loader/wiki");
break; break;
case System::Windows::Forms::DialogResult::No: case System::Windows::Forms::DialogResult::No:
@@ -994,7 +1170,7 @@ private: System::Void button_Discord_Click(System::Object^ sender, System::Event
} }
} }
private: System::Void button_github_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void button_github_Click(System::Object^ sender, System::EventArgs^ e) {
System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader"); System::Diagnostics::Process::Start("https://github.com/PDModdingCommunity/PD-Loader");
} }
private: System::Void button_Apply_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void button_Apply_Click(System::Object^ sender, System::EventArgs^ e) {
SaveSettings(); SaveSettings();
@@ -1036,7 +1212,7 @@ private: System::Void trackBar_LagCompensation_ValueChanged(System::Object^ send
private: System::Void tabPage_Resolution_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void tabPage_Resolution_Click(System::Object^ sender, System::EventArgs^ e) {
} }
private: System::Void button_Wiki_Click(System::Object^ sender, System::EventArgs^ e) { private: System::Void button_Wiki_Click(System::Object^ sender, System::EventArgs^ e) {
System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader/wiki"); System::Diagnostics::Process::Start("https://github.com/PDModdingCommunity/PD-Loader/wiki");
} }
private: System::Void trackBar_LagCompensation_Scroll(System::Object^ sender, System::EventArgs^ e) { private: System::Void trackBar_LagCompensation_Scroll(System::Object^ sender, System::EventArgs^ e) {
} }
+366 -262
View File
@@ -120,11 +120,11 @@
<data name="creditsTextBox.Text" xml:space="preserve"> <data name="creditsTextBox.Text" xml:space="preserve">
<value>PD Loader is intended for educational purposes only; not for piracy. <value>PD Loader is intended for educational purposes only; not for piracy.
Users should possess a legally-obtained dump of the game to use this software. Users should possess a legally-obtained dump of the game to use this software.
Please check your local laws/regulataions to verify the legality of tampering Please check your local laws/regulations to verify the legality of tampering
with and dumping data from protected arcade machine hardware. with and dumping data from protected arcade machine hardware.
Project Contributors: Project Contributors:
***REMOVED***, Brolijah, crash5b, ona, korenkonder, Kyberal, lybxlpsv, nastys, ano, Brolijah, crash5b, ona, korenkonder, Kyberal, lybxlpsv, nastys,
Nezarn, samyuu, Skyth, somewhatlurker, Stewie1.0, SwigS-27, zsccat Nezarn, samyuu, Skyth, somewhatlurker, Stewie1.0, SwigS-27, zsccat
@@ -237,61 +237,62 @@ AMD compatibilty pack dependencies have additional licenses, detailed in the AMD
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="button_Discord.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="button_Discord.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
rkJggg== RK5CYII=
</value> </value>
</data> </data>
<data name="button_github.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="button_github.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
</value> </value>
</data> </data>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
@@ -299,215 +300,318 @@ AMD compatibilty pack dependencies have additional licenses, detailed in the AMD
</metadata> </metadata>
<data name="button_Wiki.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="button_Wiki.BackgroundImage" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
</value> </value>
</data> </data>
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
@@ -129,6 +129,15 @@ class PatchApplier710 : public PatchApplier {
printf("[Patches] MLAA disabled\n"); printf("[Patches] MLAA disabled\n");
} }
// gamma
if (nGamma != 100 && nGamma != 0)
{
float gamma_float = (float)nGamma / 100.0f;
InjectCode((void*)(0x1404a863b), { *((uint8_t*)(&gamma_float)), *((uint8_t*)(&gamma_float) + 1), *((uint8_t*)(&gamma_float) + 2), *((uint8_t*)(&gamma_float) + 3) });
printf("[Patches] Gamma: %f\n", gamma_float);
}
// Replace the hardcoded videos with MP4s, if they exist // Replace the hardcoded videos with MP4s, if they exist
if (nMP4Movies) if (nMP4Movies)
{ {
@@ -157,7 +166,9 @@ class PatchApplier710 : public PatchApplier {
if (nPDLoaderText && !nHideFreeplay) if (nPDLoaderText && !nHideFreeplay)
{ {
InjectCode((void*)0x00000001409F61F0, { 0x50, 0x44, 0x20, 0x4C, 0x6F, 0x61, 0x64, 0x65, 0x72, 0x20, 0x00 }); InjectCode((void*)0x00000001409F61F0, { 0x50, 0x44, 0x20, 0x4C, 0x6F, 0x61, 0x64, 0x65, 0x72,
0x20, 0x32, 0x2E, 0x36, 0x2E, 0x35, 0x61,
0x00});
printf("[Patches] Show PD Loader text\n"); printf("[Patches] Show PD Loader text\n");
} }
} }
@@ -347,6 +358,7 @@ class PatchApplier710 : public PatchApplier {
InjectCode((void*)0x000000014061579B, { 0x90, 0x90, 0x90, 0x8B, 0x42, 0xE0, 0x90, 0x90, 0x90 }); InjectCode((void*)0x000000014061579B, { 0x90, 0x90, 0x90, 0x8B, 0x42, 0xE0, 0x90, 0x90, 0x90 });
} }
// Quick start // Quick start
if (!nUseDivahookBat)
{ {
if (nQuickStart == 1) // skip the card/guest screen if (nQuickStart == 1) // skip the card/guest screen
{ {
@@ -363,13 +375,15 @@ class PatchApplier710 : public PatchApplier {
{ {
InjectCode((void*)0x00000001405C84B3, { 0x90, 0x90, 0x90, 0x90, 0x90 }); InjectCode((void*)0x00000001405C84B3, { 0x90, 0x90, 0x90, 0x90, 0x90 });
} }
if (nEnablePvCustomization)
{
// Disable hand scaling // Disable hand scaling
if (nNoHandScaling) if (nNoHandScaling)
{ {
InjectCode((void*)0x0000000140120709, { 0xE9, 0x82, 0x0A, 0x00 }); InjectCode((void*)0x0000000140120709, { 0xE9, 0x82, 0x0A, 0x00 });
} }
// Default hand size // Default hand size
if (nDefaultHandSize != -1) if (nDefaultHandSize >= 10000 && nDefaultHandSize <= 1000000)
{ {
printf("[Patches] Changing default hand size...\n"); printf("[Patches] Changing default hand size...\n");
const float num = (float)nDefaultHandSize / 10000.0; const float num = (float)nDefaultHandSize / 10000.0;
@@ -389,13 +403,6 @@ class PatchApplier710 : public PatchApplier {
VirtualProtect(addr4, 4, oldProtect, nullptr);*/ VirtualProtect(addr4, 4, oldProtect, nullptr);*/
printf("[Patches] New default hand size: %f\n", num); printf("[Patches] New default hand size: %f\n", num);
} }
// Sing missed notes
if (nSingMissed)
{
InjectCode((void*)0x140109044, { 0xEB });
// Breaks border:
// InjectCode((void*)0x140109096, { 0xEB });
}
// Force mouth animations // Force mouth animations
{ {
if (nForceMouth == 1) // PDA if (nForceMouth == 1) // PDA
@@ -483,6 +490,14 @@ class PatchApplier710 : public PatchApplier {
printf("[Patches] FT look forced\n"); printf("[Patches] FT look forced\n");
} }
} }
}
// Sing missed notes
if (nSingMissed)
{
InjectCode((void*)0x140109044, { 0xEB });
// Breaks border:
// InjectCode((void*)0x140109096, { 0xEB });
}
// NPR1 // NPR1
{ {
if (nNpr1 == 1) // force on if (nNpr1 == 1) // force on
@@ -635,9 +650,15 @@ class PatchApplier710 : public PatchApplier {
} }
// patch refract and reflect buffer sizes // patch refract and reflect buffer sizes
// no need to really check anything before injecting, because reinjecting defaults is fine if (nRefractResWidth != 512 || nRefractResHeight != 256)
{
InjectCode((void*)(0x140a24424), std::vector<uint8_t>((uint8_t*)&nRefractResWidth, (uint8_t*)((int64_t)&nRefractResWidth + 4))); InjectCode((void*)(0x140a24424), std::vector<uint8_t>((uint8_t*)&nRefractResWidth, (uint8_t*)((int64_t)&nRefractResWidth + 4)));
InjectCode((void*)(0x140a24428), std::vector<uint8_t>((uint8_t*)&nRefractResHeight, (uint8_t*)((int64_t)&nRefractResHeight + 4))); InjectCode((void*)(0x140a24428), std::vector<uint8_t>((uint8_t*)&nRefractResHeight, (uint8_t*)((int64_t)&nRefractResHeight + 4)));
printf("[Patches] Refraction resolution patched.\n");
}
if (nReflectResWidth != 512 || nReflectResHeight != 256)
{
InjectCode((void*)(0x140a2443c), std::vector<uint8_t>((uint8_t*)&nReflectResWidth, (uint8_t*)((int64_t)&nReflectResWidth + 4))); InjectCode((void*)(0x140a2443c), std::vector<uint8_t>((uint8_t*)&nReflectResWidth, (uint8_t*)((int64_t)&nReflectResWidth + 4)));
InjectCode((void*)(0x140a24440), std::vector<uint8_t>((uint8_t*)&nReflectResHeight, (uint8_t*)((int64_t)&nReflectResHeight + 4))); InjectCode((void*)(0x140a24440), std::vector<uint8_t>((uint8_t*)&nReflectResHeight, (uint8_t*)((int64_t)&nReflectResHeight + 4)));
// for large reflect resolutions, adjust blur effect amount to not lose the effect // for large reflect resolutions, adjust blur effect amount to not lose the effect
@@ -679,13 +700,16 @@ class PatchApplier710 : public PatchApplier {
InjectCode((void*)(0x14050294f), { 0xc3 }); // RET InjectCode((void*)(0x14050294f), { 0xc3 }); // RET
} }
printf("[Patches] Reflection resolution patched.\n");
}
// lag compensation // lag compensation
if (nLagCompensation>0 && nLagCompensation<=50) if (nLagCompensation > 0 && nLagCompensation <= 500)
{ {
InjectCode((void*)(0x14011e44e), { 0xf3, 0x0f, 0x10, 0x05, 0x8a, 0xcf, 0x9c, 0x00 }); // hijack xmm0 InjectCode((void*)(0x14011e44e), { 0xf3, 0x0f, 0x10, 0x05, 0x8a, 0xcf, 0x9c, 0x00 }); // hijack xmm0
InjectCode((void*)(0x14011e46b), { 0xf3, 0x0f, 0x11, 0x44, 0x24, 0x20 }); // get value from xmm0 instead of xmm1 InjectCode((void*)(0x14011e46b), { 0xf3, 0x0f, 0x11, 0x44, 0x24, 0x20 }); // get value from xmm0 instead of xmm1
float startPos = (float)nLagCompensation / 100.0; float startPos = (float)nLagCompensation / 1000.0f;
InjectCode((void*)(0x140aeB3e0), { *((uint8_t*)(&startPos)), *((uint8_t*)(&startPos)+1), *((uint8_t*)(&startPos) + 2), *((uint8_t*)(&startPos) + 3) }); InjectCode((void*)(0x140aeB3e0), { *((uint8_t*)(&startPos)), *((uint8_t*)(&startPos) + 1), *((uint8_t*)(&startPos) + 2), *((uint8_t*)(&startPos) + 3) });
printf("[Patches] Lag Compensation: %f\n", startPos); printf("[Patches] Lag Compensation: %f\n", startPos);
} }
@@ -46,6 +46,16 @@ BOOL APIENTRY DllMain(HMODULE hModule,
} }
void ApplyPatches() { void ApplyPatches() {
if (game_version == 710)
{
const char* exe_ver_string = (const char*)0x140A92CB8;
if (strcmp(exe_ver_string, "7.10.00") != 0)
{
MessageBoxW(nullptr, L"Game version not 7.10. Please verify your files.", L"Patches", MB_ICONERROR);
exit(1);
}
}
std::string version_string = std::to_string(game_version); std::string version_string = std::to_string(game_version);
version_string.insert(version_string.begin()+1, '.'); version_string.insert(version_string.begin()+1, '.');
std::cout << "[Patches] Game version " + version_string << std::endl; std::cout << "[Patches] Game version " + version_string << std::endl;
@@ -70,6 +80,8 @@ void ApplyPatches() {
try { try {
for (std::filesystem::path p : std::filesystem::directory_iterator("../patches")) for (std::filesystem::path p : std::filesystem::directory_iterator("../patches"))
{ {
if (std::filesystem::path(p).filename().string()._Starts_with("._")) continue; // exclude macOS metadata
std::string extension = std::filesystem::path(p).extension().string(); std::string extension = std::filesystem::path(p).extension().string();
if ((extension == ".p" || extension == ".P" || extension == ".p2" || extension == ".P2") && if ((extension == ".p" || extension == ".P" || extension == ".p2" || extension == ".P2") &&
GetPrivateProfileIntW(L"plugins", std::filesystem::path(p).filename().c_str(), TRUE, CONFIG_FILE)) GetPrivateProfileIntW(L"plugins", std::filesystem::path(p).filename().c_str(), TRUE, CONFIG_FILE))
@@ -77,6 +89,7 @@ void ApplyPatches() {
std::cout << "[Patches] Reading custom patch file: " << std::filesystem::path(p).filename().string() << std::endl; std::cout << "[Patches] Reading custom patch file: " << std::filesystem::path(p).filename().string() << std::endl;
ApplyCustomPatches(std::filesystem::path(p).wstring()); ApplyCustomPatches(std::filesystem::path(p).wstring());
} }
else std::cout << "[Patches] Skipping disabled patch file: " << std::filesystem::path(p).filename().string() << std::endl;
} }
} }
catch (const std::filesystem::filesystem_error &e) { catch (const std::filesystem::filesystem_error &e) {
@@ -104,12 +104,14 @@ auto nTAA = GetPrivateProfileIntW(L"graphics", L"taa", TRUE, CONFIG_FILE);
auto nMLAA = GetPrivateProfileIntW(L"graphics", L"mlaa", TRUE, CONFIG_FILE); auto nMLAA = GetPrivateProfileIntW(L"graphics", L"mlaa", TRUE, CONFIG_FILE);
auto nDoF = GetPrivateProfileIntW(L"graphics", L"dof", TRUE, CONFIG_FILE); auto nDoF = GetPrivateProfileIntW(L"graphics", L"dof", TRUE, CONFIG_FILE);
auto nMAG = GetPrivateProfileIntW(L"graphics", L"mag", 0, CONFIG_FILE); auto nMAG = GetPrivateProfileIntW(L"graphics", L"mag", 0, CONFIG_FILE);
auto nGamma = GetPrivateProfileIntW(L"graphics", L"gamma", 100, CONFIG_FILE);
auto nStereo = GetPrivateProfileIntW(L"patches", L"stereo", TRUE, CONFIG_FILE); auto nStereo = GetPrivateProfileIntW(L"patches", L"stereo", TRUE, CONFIG_FILE);
auto nCustomPatches = GetPrivateProfileIntW(L"patches", L"custom_patches", TRUE, CONFIG_FILE); auto nCustomPatches = GetPrivateProfileIntW(L"patches", L"custom_patches", TRUE, CONFIG_FILE);
auto nQuickStart = GetPrivateProfileIntW(L"patches", L"quick_start", 1, CONFIG_FILE); auto nQuickStart = GetPrivateProfileIntW(L"patches", L"quick_start", 0, CONFIG_FILE);
auto nNoScrollingSfx = GetPrivateProfileIntW(L"patches", L"no_scrolling_sfx", FALSE, CONFIG_FILE); auto nNoScrollingSfx = GetPrivateProfileIntW(L"patches", L"no_scrolling_sfx", FALSE, CONFIG_FILE);
auto nEnablePvCustomization = GetPrivateProfileIntW(L"patches", L"enable_pv_customization", FALSE, CONFIG_FILE);
auto nNoHandScaling = GetPrivateProfileIntW(L"patches", L"no_hand_scaling", FALSE, CONFIG_FILE); auto nNoHandScaling = GetPrivateProfileIntW(L"patches", L"no_hand_scaling", FALSE, CONFIG_FILE);
auto nDefaultHandSize = GetPrivateProfileIntW(L"patches", L"default_hand_size", -1, CONFIG_FILE); auto nDefaultHandSize = GetPrivateProfileIntW(L"patches", L"default_hand_size_uint", 0, CONFIG_FILE);
auto nSingMissed = GetPrivateProfileIntW(L"patches", L"sing_missed", FALSE, CONFIG_FILE); auto nSingMissed = GetPrivateProfileIntW(L"patches", L"sing_missed", FALSE, CONFIG_FILE);
auto nForceMouth = GetPrivateProfileIntW(L"patches", L"force_mouth", 0, CONFIG_FILE); auto nForceMouth = GetPrivateProfileIntW(L"patches", L"force_mouth", 0, CONFIG_FILE);
auto nForceExpressions = GetPrivateProfileIntW(L"patches", L"force_expressions", 0, CONFIG_FILE); auto nForceExpressions = GetPrivateProfileIntW(L"patches", L"force_expressions", 0, CONFIG_FILE);
@@ -127,3 +129,4 @@ auto nReflectResHeight = GetPrivateProfileIntW(L"graphics", L"reflect_res_height
auto nRefractResWidth = GetPrivateProfileIntW(L"graphics", L"refract_res_width", 512, CONFIG_FILE); auto nRefractResWidth = GetPrivateProfileIntW(L"graphics", L"refract_res_width", 512, CONFIG_FILE);
auto nRefractResHeight = GetPrivateProfileIntW(L"graphics", L"refract_res_height", 256, CONFIG_FILE); auto nRefractResHeight = GetPrivateProfileIntW(L"graphics", L"refract_res_height", 256, CONFIG_FILE);
auto nLagCompensation = GetPrivateProfileIntW(L"graphics", L"lag_compensation", 0, CONFIG_FILE); auto nLagCompensation = GetPrivateProfileIntW(L"graphics", L"lag_compensation", 0, CONFIG_FILE);
auto nUseDivahookBat = GetPrivateProfileIntW(L"launcher", L"use_divahook_bat", FALSE, CONFIG_FILE);
@@ -82,6 +82,7 @@ namespace TLAC::Components
MenuCircleBinding = new Binding(); MenuCircleBinding = new Binding();
CoinBinding = new Binding(); CoinBinding = new Binding();
ToonBinding = new Binding();
FileSystem::ConfigFile configFile(framework::GetModuleDirectory(), KEY_CONFIG_FILE_NAME); FileSystem::ConfigFile configFile(framework::GetModuleDirectory(), KEY_CONFIG_FILE_NAME);
configFile.OpenRead(); configFile.OpenRead();
@@ -100,6 +101,7 @@ namespace TLAC::Components
Config::BindConfigKeys(configFile.ConfigMap, "MENU_L", *MenuLBinding, { "Left", "Up" }); Config::BindConfigKeys(configFile.ConfigMap, "MENU_L", *MenuLBinding, { "Left", "Up" });
Config::BindConfigKeys(configFile.ConfigMap, "MENU_R", *MenuRBinding, { "Down", "Right" }); Config::BindConfigKeys(configFile.ConfigMap, "MENU_R", *MenuRBinding, { "Down", "Right" });
Config::BindConfigKeys(configFile.ConfigMap, "MENU_CIRCLE", *MenuCircleBinding, { "D", "L", "Spacebar" }); Config::BindConfigKeys(configFile.ConfigMap, "MENU_CIRCLE", *MenuCircleBinding, { "D", "L", "Spacebar" });
Config::BindConfigKeys(configFile.ConfigMap, "TOON", *ToonBinding, { "F9" });
Config::BindConfigKeys(configFile.ConfigMap, "COIN", *CoinBinding, { "F10" }); Config::BindConfigKeys(configFile.ConfigMap, "COIN", *CoinBinding, { "F10" });
mouseScrollPvSelection = configFile.GetBooleanValue("mouse_scroll_pv_selection"); mouseScrollPvSelection = configFile.GetBooleanValue("mouse_scroll_pv_selection");
@@ -168,6 +170,12 @@ namespace TLAC::Components
// repress held down buttons to not block input // repress held down buttons to not block input
//inputState->Down.Buttons ^= inputState->Tapped.Buttons; //inputState->Down.Buttons ^= inputState->Tapped.Buttons;
if (CoinBinding->AnyTapped())
addCoin();
if (ToonBinding->AnyTapped())
toggleNpr1();
} }
HoldState InputEmulator::GetHoldState() HoldState InputEmulator::GetHoldState()
@@ -299,9 +307,6 @@ namespace TLAC::Components
if (buttonTestFunc(RightBinding)) if (buttonTestFunc(RightBinding))
buttons |= JVS_R; buttons |= JVS_R;
if (buttonTestFunc(CoinBinding))
addCoin();
return buttons; return buttons;
} }
@@ -345,9 +350,6 @@ namespace TLAC::Components
if (keyboard->IsIntervalTapped(VK_SPACE)) if (keyboard->IsIntervalTapped(VK_SPACE))
inputKey = 0x20; inputKey = 0x20;
if (keyboard->IsIntervalTapped(VK_F9))
toggleNpr1();
if (keyboard->IsDoubleTapped(VK_ESCAPE)) if (keyboard->IsDoubleTapped(VK_ESCAPE))
*(bool*)SHOULD_EXIT_BOOL_ADDRESS = true; *(bool*)SHOULD_EXIT_BOOL_ADDRESS = true;
@@ -39,6 +39,7 @@ namespace TLAC::Components
Input::Binding* MenuCircleBinding; Input::Binding* MenuCircleBinding;
Input::Binding* CoinBinding; Input::Binding* CoinBinding;
Input::Binding* ToonBinding;
InputEmulator(); InputEmulator();
~InputEmulator(); ~InputEmulator();
@@ -23,12 +23,12 @@ namespace TLAC::FileSystem
return found; return found;
} }
int ConfigFile::GetIntegerValue(const std::string& key) int ConfigFile::GetIntegerValue(const std::string& key, int defaultval)
{ {
auto pair = ConfigMap.find(key); auto pair = ConfigMap.find(key);
bool found = pair != ConfigMap.end(); bool found = pair != ConfigMap.end();
return found ? atoi(pair->second.c_str()) : 0; return found ? atoi(pair->second.c_str()) : defaultval;
} }
bool ConfigFile::GetBooleanValue(const std::string& key) bool ConfigFile::GetBooleanValue(const std::string& key)
@@ -14,7 +14,7 @@ namespace TLAC::FileSystem
std::unordered_map<std::string, std::string> ConfigMap; std::unordered_map<std::string, std::string> ConfigMap;
bool TryGetValue(const std::string &key, std::string **value); bool TryGetValue(const std::string &key, std::string **value);
int GetIntegerValue(const std::string& key); int GetIntegerValue(const std::string& key, int defaultval = 0);
bool GetBooleanValue(const std::string& key); bool GetBooleanValue(const std::string& key);
float GetFloatValue(const std::string& key); float GetFloatValue(const std::string& key);
std::string GetStringValue(const std::string& key); std::string GetStringValue(const std::string& key);
@@ -16,6 +16,8 @@ namespace TLAC::Input
config.OpenRead(); config.OpenRead();
xinput_num = config.GetIntegerValue("xinput_preferred"); xinput_num = config.GetIntegerValue("xinput_preferred");
rumble = config.GetBooleanValue("rumble"); rumble = config.GetBooleanValue("rumble");
rumble_left = config.GetIntegerValue("xinput_rumble_intensity_left", 8000);
rumble_right = config.GetIntegerValue("xinput_rumble_intensity_right", 4000);
} }
Xinput* Xinput::GetInstance() Xinput* Xinput::GetInstance()
@@ -256,8 +258,8 @@ namespace TLAC::Input
{ {
XINPUT_VIBRATION vibration; XINPUT_VIBRATION vibration;
ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION)); ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION));
vibration.wLeftMotorSpeed = 8000; // use any value between 0-65535 here vibration.wLeftMotorSpeed = rumble_left; // use any value between 0-65535 here
vibration.wRightMotorSpeed = 4000; // use any value between 0-65535 here vibration.wRightMotorSpeed = rumble_right; // use any value between 0-65535 here
XInputSetState(xc_pref, &vibration); XInputSetState(xc_pref, &vibration);
} }
else else
@@ -48,7 +48,7 @@ namespace TLAC::Input
void SetTapStates(BYTE keycode, float elapsed); void SetTapStates(BYTE keycode, float elapsed);
int xinput_num; int xinput_num, rumble_left, rumble_right;
bool rumble; bool rumble;
}; };
} }