From f597fedbcfc23646ba85f0d3c7ed97acc93b8520 Mon Sep 17 00:00:00 2001 From: nastys <@> Date: Fri, 26 Feb 2021 00:24:12 +0100 Subject: [PATCH] [Patches] Lag Compensation; [Launcher] Acrylic and Light/Dark themes and other improvements --- ...aderPatch_template.bin => ShaderPatch.ini} | 6 + source-code/data/plugins/config_template.bin | 10 +- source-code/dependencies/GPUModel/GPUModel.h | 5 +- .../source/plugins/Launcher/ConfigOption.h | 57 ++- source-code/source/plugins/Launcher/Help.png | Bin 0 -> 22061 bytes .../source/plugins/Launcher/Launcher.vcxproj | 2 + .../plugins/Launcher/SkinnedMessageBox.h | 9 +- .../plugins/Launcher/SkinnedMessageBox.resx | 3 + .../source/plugins/Launcher/composition.h | 99 ++++ .../source/plugins/Launcher/framework.h | 23 +- source-code/source/plugins/Launcher/ui.h | 479 ++++++++++-------- source-code/source/plugins/Launcher/ui.resx | 215 +++++++- .../source/plugins/Patches/PatchApplier710.h | 11 + .../source/plugins/Patches/framework.h | 3 +- 14 files changed, 699 insertions(+), 223 deletions(-) rename source-code/data/plugins/{ShaderPatch_template.bin => ShaderPatch.ini} (89%) create mode 100644 source-code/source/plugins/Launcher/Help.png create mode 100644 source-code/source/plugins/Launcher/composition.h diff --git a/source-code/data/plugins/ShaderPatch_template.bin b/source-code/data/plugins/ShaderPatch.ini similarity index 89% rename from source-code/data/plugins/ShaderPatch_template.bin rename to source-code/data/plugins/ShaderPatch.ini index e3d5b4a..6a45d15 100644 --- a/source-code/data/plugins/ShaderPatch_template.bin +++ b/source-code/data/plugins/ShaderPatch.ini @@ -54,6 +54,12 @@ hair_npr1.*=cfg:toon_hair_improve||from:MUL spec.x, tmp.x, 0.7;||to:MUL spec.x, tone_map_npr1.*=cfg:toon_lines_improve||from:MUL density.y, density.y, 0.25;||to:MUL density.y, density.y, ; tone_map_npr1.*=cfg:toon_lines_improve||from:MAD density.w, density.x, 0.7, 0.25;||to:MAD density.w, density.x, , ; +# Intel related patches +(?:movie|sprite|imgfilter).*=cfg:intel||from:; ||to:;\n +(?:movie|sprite|imgfilter).*=cfg:intel||from:(?:RET|TXL|NRM|OPTION NV_fragment|PARAM p_charfragment.color|ATTRIB).*?||to:## +(?:movie|sprite|imgfilter).*=cfg:intel||from:(?:SHORT |LONG ).*?||to: +.*sprite.100.fp.*=cfg:intel||from:MUL result.color, col1, fragment.color;||to:##MUL result.color, col1, fragment.color; + # Debug patches: # Nametags # Adds comments with the shader file name to the shader text. Useful for debugging issues diff --git a/source-code/data/plugins/config_template.bin b/source-code/data/plugins/config_template.bin index bd6a8f8..efdb342 100644 --- a/source-code/data/plugins/config_template.bin +++ b/source-code/data/plugins/config_template.bin @@ -7,7 +7,7 @@ Enable=1 [GPU] -# Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell, 2=Turing +# Force GPU model -- -1=auto, 0=Kepler, 1=Maxwell, 2=Turing, 3=Ampere Model=-1 [Launcher] @@ -15,6 +15,10 @@ Model=-1 Skip=0 # Disables unsupported GPU warning dialogs. No_GPU_Dialog=0 +# Sets the dark colour scheme in the launcher. +Dark_Launcher=0 +# Enables acrylic blur in the launcher on Windows 10 20H2 or later. +Acrylic_Blur=0 #Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing OpenGL_Patch_A=0 #Ignores some OpenGL-related errors. Don't use both patches at the same time unless you're know what you're doing @@ -88,6 +92,8 @@ Custom_Patches=1 Prevent_Data_Deletion=0 [Graphics] +# Lag Compensation +Lag_Compensation = 0 # Set to -1 to unlock the frame rate. FPS.Limit=60 # Reduces FPS Limiter CPU usage @@ -121,7 +127,7 @@ NPR1=0 FRM.Motion.Rate=400 [Resolution] -# 0 = Windowed, 1 = Popup (recommended), 2 = Exclusive, 3 = Failsafe +# 0 = Windowed, 1 = Fast, 2 = Exclusive, 3 = Safe # For same as screen res: -1x-1 Display=1 Width=-1 diff --git a/source-code/dependencies/GPUModel/GPUModel.h b/source-code/dependencies/GPUModel/GPUModel.h index c91cebc..ff30ed1 100644 --- a/source-code/dependencies/GPUModel/GPUModel.h +++ b/source-code/dependencies/GPUModel/GPUModel.h @@ -34,7 +34,7 @@ namespace GPUModel // note that the used GL context may differ std::string getGpuName() { - // detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing + // detected model can be overridden -- 0: Kepler, 1: Maxwell, 2: Turing, 3: Ampere int nGPUModel = GetPrivateProfileIntW(L"gpu", L"model", -1, CONFIG_FILE); if (nGPUModel >= 0 && nGPUModel <= 2) { @@ -50,6 +50,9 @@ namespace GPUModel case 2: arch = "TU000"; break; + case 3: + arch = "GA000"; + break; } printf("[GPUModel] GPU Model override: %s\n", arch.c_str()); diff --git a/source-code/source/plugins/Launcher/ConfigOption.h b/source-code/source/plugins/Launcher/ConfigOption.h index f93e2c6..4abe2cd 100644 --- a/source-code/source/plugins/Launcher/ConfigOption.h +++ b/source-code/source/plugins/Launcher/ConfigOption.h @@ -19,7 +19,7 @@ using namespace System::Windows::Forms; float BaseScaleSize = 96; int Col1Width = 110; -int Col2Left = 114; +int Col2Left = 140; int Col2Width = 90; int ConfigBtnLeft = 120; int ControlSpacing = 6; @@ -301,6 +301,41 @@ public: } }; +class OptionMetaSeparator : public ConfigOptionBase +{ +public: + OptionMetaSeparator() + { + } + + virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip) + { + Label^ lab = gcnew Label(); + + lab->Text = "_____________________________________"; + lab->Left = left + 2; + lab->Top = top; + 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 BooleanOption : public ConfigOptionBase { @@ -331,7 +366,7 @@ public: cb->FlatStyle = System::Windows::Forms::FlatStyle::Flat; // hack to ensure high contrast - cb->BackColor = System::Drawing::Color::FromArgb(0, 0, 0, 0); + cb->BackColor = System::Drawing::Color::FromArgb(0, 127, 127, 127); Form^ RootForm = panel->FindForm(); float ScaleWidth = 1.0f; @@ -534,9 +569,10 @@ class DropdownOption : public ConfigOptionBase { public: int _defaultVal; + int _indexOffset; std::vector _valueStrings; - DropdownOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector valueStrings) + DropdownOption(LPCWSTR iniVarName, LPCWSTR iniSectionName, LPCWSTR iniFilePath, LPCWSTR friendlyName, LPCWSTR description, int defaultVal, std::vector valueStrings, int indexOffset=0) { _iniVarName = iniVarName; _iniSectionName = iniSectionName; @@ -545,6 +581,7 @@ public: _description = description; _defaultVal = defaultVal; _valueStrings = valueStrings; + _indexOffset = indexOffset; } virtual int AddToPanel(Panel^ panel, unsigned int left, unsigned int top, ToolTip^ tooltip) @@ -562,12 +599,12 @@ public: for (LPCWSTR& choice : _valueStrings) { combobox->Items->Add(msclr::interop::marshal_as(choice)); } - combobox->SelectedIndex = GetIniInt(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath); + combobox->SelectedIndex = GetIniInt(_iniSectionName, _iniVarName, _defaultVal, _iniFilePath)-_indexOffset; combobox->Left = left + Col2Left; combobox->Top = top; combobox->Width = Col2Width; combobox->AutoSize = true; - combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + combobox->FlatStyle = System::Windows::Forms::FlatStyle::System; combobox->DropDownStyle = ComboBoxStyle::DropDownList; Form^ RootForm = panel->FindForm(); @@ -600,7 +637,7 @@ public: virtual void SaveOption() { - SetIniInt(_iniSectionName, _iniVarName, Convert::ToInt32(((ComboBox^)ComboBox::FromHandle(mainControlHandle))->SelectedIndex), _iniFilePath); + SetIniInt(_iniSectionName, _iniVarName, Convert::ToInt32(((ComboBox^)ComboBox::FromHandle(mainControlHandle))->SelectedIndex+_indexOffset), _iniFilePath); } }; @@ -651,7 +688,7 @@ public: combobox->Top = top; combobox->Width = Col2Width; combobox->AutoSize = true; - combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + combobox->FlatStyle = System::Windows::Forms::FlatStyle::System; if (_editable) combobox->DropDownStyle = ComboBoxStyle::DropDown; @@ -756,7 +793,7 @@ public: combobox->Top = top; combobox->Width = Col2Width; combobox->AutoSize = true; - combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + combobox->FlatStyle = System::Windows::Forms::FlatStyle::System; if (_editable) combobox->DropDownStyle = ComboBoxStyle::DropDown; @@ -889,7 +926,7 @@ public: combobox->Top = top; combobox->Width = Col2Width; combobox->AutoSize = true; - combobox->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + combobox->FlatStyle = System::Windows::Forms::FlatStyle::System; if (_editable) combobox->DropDownStyle = ComboBoxStyle::DropDown; @@ -1032,7 +1069,7 @@ public: cb->FlatStyle = System::Windows::Forms::FlatStyle::Flat; // hack to ensure high contrast - cb->BackColor = System::Drawing::Color::FromArgb(0, 0, 0, 0); + cb->BackColor = System::Drawing::Color::FromArgb(0, 127, 127, 127); button->Text = L"Config"; button->Left = left + ConfigBtnLeft; diff --git a/source-code/source/plugins/Launcher/Help.png b/source-code/source/plugins/Launcher/Help.png new file mode 100644 index 0000000000000000000000000000000000000000..6b740954d5ce2665fd79450efcdf8edeffebaaa4 GIT binary patch literal 22061 zcmYIvbzD?kwDvH73?&Q>T|+k_4H84i5W>)nqzKXo(lB&LjdXX3Gy;k=N+?K)v{Fik zARzUf@xAxEfAGU|&OUqfv!1;U#-g-TNr~u)Kp+sQ8d6yo1OoE_KYWl|z#U#QLP`*b zoz!37_?fQtbGW;w+ha#(d-yXycYCwX=5J?#q~S9oZp>%xs+l2yi!J-wHW!w^F2eWM zgC_D$uCA}(ezL)qWaj}z!E(z}OFO4ZdCSDF_vx2Wogqhc)jrP`v+fX+KhdBuA`Ut zx-Nc%9L+DjYgX=QE%4S2Eiufs=Jx!X^BkJ&-sQpPh7Ji1>Dv#Bc3Nw{jrLYGSkvn~vl)xy0wT?I}tnr5FvK7GuZSV_~Q2 z_H@%%2Iz%)yV*Dck*8l>nx{PZUW-3{eIo9^LrB8^-e>#usoaBS;q;`nV!k)u(`X&C z{nAY;K8s&4#2=gZr5R+re)E^^{$4XW)}nRy%>@%z8?J6{;BeJPt@~FmG-?;0{T67o ze7F1Oez1x_;K-k`uAA`6NVln#_|zqbuHp}`Mt6QvD7fpwL|Cc3;49^jC!DJ;hAznDwYf4Hp8QH@vR3%^{SnXYwkeJkM_EQ@kSf>O3xT zDqRj2{Gk{6MPH}5s*_G%d}9dd_*oZnCDu1=n<}W-oOxdY5@3`eOkBj=!`WV;Law#a z`g!8s z{^R3wt@PbbJ`WD_Uf6*gTReum8_PMb+pkzWRj3c`^naZ{Sf21%J3O}AB|b>*IKR2r zy51z9P*k1~@wAm2Hym}JPpohW^?H-;^10b)=XoQ)>!+rn2q!MiC5AqBU$pvm6IZ(1 z`lRtDj;7PsS9wxeY+jFJKlwxw9ipfbw`9L75oSM^pUgNVyZJ4)<7p;lBSVGH;Q!G5 znBiqEdkP}*eyYQs^Ps=wt%^px_Gl#Ix* zqC}G#+twFme{NlEk-Ss1IMLTvjD?Sv{q>P<;@<-wpxFnL)Oy-=!lo1L7EJH-oH+Dc z0zh}Q7wJjFM^5;rbur*GJ>lfvjyK|&M$M`@i%@*_oXO8m>OS!a-1f4muUqNGV$WAUR*l zFFZl4U;c!ae=Ga1nGw}Ww^W(yV0Eo+jo<6ld&ysF_nh*-)tKUg1=b^<@t5Y@WmK8y z)$*Q}%q{bm7p`ONcte0rhc3Uw$82jUaIe+tTo($Ux*00TDOwdIU#0uHE`3jV9Z+Cr zR4byw)}z2AL^`TQd6x=Z>hWB@QkyJr{~-rS_brO|p!HiFc-Iv#WJKEfb~&M;ht9ZC z0qH%gpBJ{%%+n?vU(H$mVE9^=s(HSFE0{D_b^U{YI4^7TNrkr(y&2V>x4?+qm_^K=&pj;deSXWTL+LcPh&Jw>6c+r*-R&Pi@zcRU`{s8O){ zjBPo<%U&{UvP*=Y3e>%k;S+%3vYdd(g>R zhzPf%zcyQ}@El@TSxZv7k1q0_nzvFUBpJ(I3`ClCjQo04RGBlRl6;lC+Lj*|MXXx& zcUZCy?38tmJ|6Np^k|H=a+J{4u18h}_3sbj#p&^~2xdal+;61>fGqBxSi%QAWh9C8 zyMylIHWCw=Kk1TVcd7jrF=EEPI8K;qp<~f4BwJw`Xll3gjOF1<>R>`zg;mh<8yPeS zeUFMR9N#2EMR05R!>3+LO_@i96ejn$wg;!EBtL~=8jZvFT?d#!)ZG+2PUiKx;ujlB zub0d|;WqHP>NboHY&X#nee2o9=uUInbm^Lu;9MJdGp$OfT47Z=!NM zUJ1=`&^K%!-H+u2&2f&@TiwDd84e|~(czHgeygdV@kp`5j^(LZ%x)2T8f*oBZo%+z zO7wRKqT`KDC2PM^iF@6z8Kx<(Yyoq&X`ONR1)KAE#H0!p14?qT=rh6egQAOAp-9ak z7I*uX&{cTP*qY6o4}R*u;IA`7Ra4kfY3T}wSNsI=jt2x?B@ry9JEByC*5O)v6|Zu+ zB6+}ND64f#<*FA6JN5=yOGK>!&#xYsDY+t6=wzu=pXsUe6>+^Fy-)F2ES1I*psv*gCi35`)M+SkZzP9OL1BK|35BNx^ac zR#HR_g>t5`FBTvENnF-$gq@KzGKhf8EF+kGZ0}7f48i@*Mrqh>tP3A-FA!l=#9e(W}WIP+0Hc=5fO&(_`JisJu_>Iyd;mX}h)a3RAZ)V2v99?#l))}r$#FEx< zdH2fP(K%9ivmg(D0L_v~{%fF!nLNF}1)?|K%cLKGmQ&CS zg=^=OUuD%E?%9gei<`rg5bXjlCT;iwC9=q)CJ$Yd7RHcSwigsOwtck1;F0>L@}`(C z1`G@RT?4a3k3yBpDjeiu+0qS@SREI?{UN`{gY-KZ=Df28t$xG!EaN4AZ-wek8G$tpF%~qU&NDN3VqpO)mn_N zl6~$XX>-r<#A$ZgWBj#?V9=8u8C}^&U%lg>jb%8|SAPwaKbR8g)eJ;NMQP%c{HYM5 zIK%kIY~H>b{|Q2R@^IqCNK8K~iRx{Bt+k04@vWg<_h5LpK|WPNo*PV>oNn_Suf&W= zi`&J(H17;%SVWUu|ESkmx5@Gn>K!Vx7YklVH5ENfj@FDMIOA;k^QFUEwdiC%T1a0W znnJf0nVwat0}ppjoMM(tvQ*XNKWL=J6aEA0;4}7r{Yt5w|1)&l5yI^*@$AJ5h3OGH zCEt+nvK4r^DAyG|8D_rpiOX;$xBaxWYS-DH5m?c&-B$&Kds=Slw&hWW#cPpXiF|+D zLgN;1a#EZlQ&)b)S)SlQc3z3Y&u6L4f7zZEs@FnPsavBW6xxwJ{%qu7o*AJbX=~r{ zgrG&`QAC2bXo;k62esAP5xgGxSQ#JIhO;?X#@jGO{5x0QxnH}e$|9vtK2`eg`T=LN zd{$S;U%J6XNY2Vual9N=z0y30oMJfk_`v2ZE=)#Es3^>pNQ;&b{!|tYwBI`~?Qk#znF6Imd^0QCJ z*X#U-hdnb8NPbZ@c$sW$Bjdr5XKKQa&%RGhlm50XlH+M242|#Z#I2mkP#b(J`N!uj z(+)6+Mj6FrVn8U~3+o6FtF${YUWiNXmwaNAQr=;LF8n-WH)`p*NRVQz25BLwi%ief#Cgg@7=oq2v=gInTFY*!ECjy_Mry)xEn@ zR%zzta@G{7S>QN=ew8OBv9GG;AM}q$rPdgI^*tGOnxw-A5%WiaDjmTx>>|@XM7sA5 zQs#_&ZF*zwAiHal8Xsx=c@O;&I_^oF6@^skUQE1PnvpjGAK@I~ZGDSh?9maw{1J_S zywLvW#T=M>_8b=X)#l`3Tnqy>20T(KK1y=m&Geh>xBPGFXoE~92KKFTKLI` zOwZ>Il%7S@YK?lcZdud%A@chwn9f7v*W=;}fr-MJ{@n9JX%)YsHLt0h7{#xhgCx7j zgq@7*nMFCQQgb-X8Cw(usB86UPV0yzCqa$_Xv?IoBSxbgM*WyGrXzu9FNkj{CMG0(q)T zUeHVDAn|F#M3=q&mrE0(r^1r^UD2PEn<+g174^frv-k+g+Pj`jUyfEV&`U>duwhPs zjcCL8oGgf}`$2`(=wCuU>BEBio^6udL@R@Vef}yi8=h}e?l`!saGYY(FBOur^kh;I z)fF36s)LMA!}q(ptLwjLlrL;0MBtQrBC6OXO*4l}KHGdJML&?S*M&Z4`A7`;NSZ!J z9Pw~9VSD!#hgbuF#%)j)apB*$i9`uhYK}@#8{=#@dFrX_-^l`#R))9{?3<#cH#KH? zs3H5M#(T{PJVMMid%bm$WOYbP`AfU7f@eX2fv33(bg|i}u@9{gmr%!)Z z+BE4in7w1?;yfwP$*LDWV8BgozD!IAU`_r2Wqfo*?;sUFrn2kY4{Iq2nv+Dy=rhIL zX&ng@<|TnN20kFq(&bR_V5H4Z@o=UJX)Yu5;e0dA|IWpFW+o@JMr4N0G_O)nGl(ks z$WAK#tx%!Iv`Z+ZC4O`$l{tP^1k4N*yrxFDD)A6cPNAmiyQuVmUR55R(0gkiJR=}qCbTds#}>YT8wDHNNhWqn*Y z@#v$4C`|O&-D87Ad=~*7=u&i9CGz5loQfD%ps?N#zgyWn?+RpjPMdh}ty4&+=voC* zoBmR#KEhLpb_>RD?s@wwIR1>zctiajoW*^Idu{E2Wz+OQQsK>+t2!;(t7VV_Givt5F$ZoPG--S+Q(TaE%}OufjY}|J*O_ z$8K8#%qv&Y1?+Y>8AaaR+sbLehX|C6N%)7b&!`#FRhs*RX3Bn60j|sks-VDuh>L(n zwRxkhK|g<%1TP(&mfDBCK& zCnx$E<=NIMwMQJU@Ijw-JsC&3#h>uj?R6J*{+JYx4e$I9`Gq z;}cLtbv25!20TM_|W)k~$MMZlwSs<>9vMyW1AYqLU;$Yp6#VYGok) zrp4x+bcw1}k6iL-YL*PrVd@^+Lr_!ZiIka8Kr!Lg$<+PQisIg)lppn)j0?%Vd(x)A zQ%=9^@U`4BwH@R^Ha2f{XnJ}Ido|8Ey^=e)(}*(;F%jS>QY18Dq(?yau>}E;- z!lgeF$WCtgdo}KU+V{DZ2i{1bs7UiD$LR}FX}vc>PsT-9+(q1?ExONyS}naf`EN6( zd?U)y5>YsrYs@^je};EKVi188WKVke#MhN4+=9Wx@Gj@&hoY<2;1SrkQhKO%O@Q2`YRpYm?#*>PM_@|eea{1Hl|C}y+ z8&&9$soNr`M#dWCccWR?9u=tEXZUzV{)&0GPx%`C(t@^B^`h%*#*?^Xp9kN_uZ$^j z>D`aTqo0K#U8;@XG{_TwkuOFlwwNRO<_7D$IbrUZN?+ zY<^18>J6qD^+Bbht1aH`$Z6YMkR*rE9roF$FP<%ubGKWXCH%77qDtQw1Av`pCzUY_|wJ zv!NUr(EHI@$u-1tLbm+j{YzJ+!?DY`ju??&cX?3M#?#kgjfYNp8#u%(&`eN%M2Vy( z`FY2~id|60IL&g*^6qU%4Fw8vBE#d^?hqF$Heplh2kTKEQ>`B9kzPteju`}poP~Jr z@_-i2acL26Uk7~eLQ8)ySr}Zc`sg-S)o~I?XZUalIjjd1-7f<{H-+%#Qg&=M zKd8;Q*$j2})%JmI^L;7~u`z%WY_$%pJBk!InL$4udeYZm9P@En$Xn(Y4crqBAhx%@ zC#~yJ$AOvx7dY~2nP4rTTVg`fU(+W?je|mTzU65MLysf<+kV~9$4M>irwu1bDcs@Z zzk`=r@CQmx*b;iiRaJo-+p(u0$@47YA(Jj+WWnq09by%Hg=g1uzIKm)xiB)*OI4OG ze;B-PcPkM0Cuz_ZjTdVvGbV)$9}#l8Nz!D{hzX&BH~YS}hxBO!%~szNUiX|K6ZCF5 zZCi!R--eg^+*t;2L=qJ@H;v$59CNq_{sx*2yx75G9I5*eUX*OC&FBq&aG!^xnO*C+ zKc&@t^@XqYt%ef!-Q#Q6qlpiD6Il$g!s&O}`fsoKwTNApP!YJQqQpEwjHrR1QO)B7 zCkUyRBGkI4HLGYQ#Cs)6c)yDHF7Ni3!;kMJx2;Wv#d1uYt$3=%#7|k+(0(q^P+fy} z=9GOwC4XDio+_mEaBpde3C=DucX#OO35Ib0vRn1#e2F%XZc%A5#hOx05D{t@J-56cg;xymwi8r*&~d7s^R_Bj0+G?;R*qk)Pt(0Pm;8;U=ljQ>p%WXX$uj(< zSD!T=Jo!j~i);ILo$j2jxr~$7S2I~+L`gU(r}Ct3_f5D{@)m!ffJcf|{UCA&2udYmVuG{XT70AWfMI&Rr1WC)e^6! zhsSu$-=E$Su4P??o28d0Q#|iXhtVpX5E_$M{m2*<)^<7Q+gFFltR?StFBfVfSyDq* z)2W-RRUNqAudxr?$|@uXxxT%{+MxK|D9GATGvGq9JX~eUx&M6iBHrOU{jhqC<;&EG zJ90>75Xj5EyZVo)Ld0j1#6&_yv0JIAxj`lGU&^8WEqv}{4rqR-o3)Y`H-D0yC(+w| zWm~Fi&M&Oc3im#?IVMq&TK+snZH885&p_==dp5x zcKXP@e~b~&wLZbA@B8q?-s2^UXsOipy!lRdPudy*uaF1+oa?6S&6MyDuF6!Nmaj>r z+ws4Yw-X}%#u+R=eW8Wo>uc7?;b@r@l=jo9S94lhjk&EisdZ~A?uv}G!fER*`evFM zN>3NRkjs8MO;1*eytz+f&D*@G^Edfc$h!*oVAAWi61=oD+iuaECnsM0C%;5R$qyG? zlUve)A}=F1w`L+BOxAY#B2M`Wc@XdPDt3Y2d(w-v@t+dTs2@&b(B zQqobcnA{?g!o@pU+?L*r=0;{Kh)?g2H;GKyF@CFodFPgNe3tqYSnH20!!e!Hie>V*1xUy zW!bV2cP7VlY>qAXd$bkKWyx&;!hM9i_92E{$>C}D(b$mFFDplf=0R>watd6JsYsP) zb?0+iIyu2P^4;mCJTb|B6>nx+PH4O}zqT#9&3#gOR9tfN=M0bVK`KZ=*0=FXuh|=) zsRGi$J^7Emp{BA#aDRp^YZcl4PUw(FWd4;j;ko3YS1(K2r~CoLi%>k+q8w{`?; zkegp)Wf0+k{*KB73kW&I_cXF~!!~wO5TP%=qoLDdO}N>NR9evh)4gR4(~yyd;1=jO zN&i&+sx|wZ;yHrOm6?mSxaCxrE9kZ|9A(pF`F1@j{|6O`+8fA?lTEztg-Q z9|tng^jK2pgXmQde$A&=7|nOL$j%8w_qs>7X$Sj{h3%dci1A6|ZcjuR6{>$KdfU)_ zd`$2%xOrdLLsuHk_K-8a=c&cTaog7P5Axw-lV>L5c1rehQ>8zGzZ-_WZk|@s)l+`I zTP)(9{37vlpP{igqt9fg%J^Xh+}<#c1LW3(+9LTh^91|_vk4^$s4!zw_H#O&Qx{N- z7z?I+j$?b(y}3=W$LJU4GKu1A4!1NSTT-t3DL2@4nW(JecT!yvo-BP-GZ^T7ZtS#c z4YrZqONnW49_^R^g--ku;*(+)v|Ark_~4(^17#H>DEU%YQFVpsASP)>jjwtZpY%sf=r3oh-)4#p zd##FuJmr&pdUP6%SnLYkk#{q) zO*`#nQPuu)22z8xrm}0~D0}#z9b6<`P(O9gFcDYU$D3}J?eMG|W-hhxt~<}? z%Xg@WeTFHq|E~(hT#%mq-!(xHLbUg9cdPh!f5lhTDivOxO84J>FCL71<+zwAQ917cRNGxsYR0clXrdH!*khF!YHGYOFOn; z>Dl29iguh@3pvBa{1jWBB36nNZq?`ABugRUPiwSIQXKWrrRNJ$j*; ze(0+rcS#jhvX~h2ano7J(SMDNYPZ8NLwyW|cc6Ij-ovg`#`v>Uy3dtS&^yo_)yAgW zsc9X?^713jtUEXY?>9pxgpSwnogeh|iITww_jf{5P@6fqK<>n^;*Z0HnzMR#ZkEICn(@0!s=QA0yO38+YY*gMdE=$_+}9MfM>W1|I3Dq{M}%RZH4cYEdbxFqFlq)T8Ez zUQ1`1|HXeuhk;S6_OyKe{?TT-XTZdWz(|4o66E3KrTZ*};wA%T+VAVWko5eN>G?jW z$ntUZ>^+>yY&mh0%Zwc0#Wp@ym?}5U#-`XJ)*D83{es^Ec2I*1#>caQ`y0Dae zAsGakn3_H!b$5rnpyUo%TwPq;eSZ~DKD$ize897+J*OcF_J|J z#S*wf=#Dh;0)dF{V1IBx*|{{pO@e1?4^;@(!L*drj74iJLLd+vq^7K(?>o1<=;CZ~ z8uaaunPV2_5?z#S+#sU9$IcZ@PS2qpnrtDa^U8pX-dwVq-z8vLp^v}2o0B&3jRfz2 z6CaTqWjiI)4kh@OGYzj4B7sij$53Tul|Za`x>AnkR=*v83YCj`V=e8h=*hFw-Xg`x z(*EdxJz27Xv3O%Bhg@zz<;D8`P1nzpYT|!l2G;n^AYQDytNfM)WdLc_=WftlfLj zLzP;Y2=RHv#y zix_GeAWA{X%F5b5H7ushm!N#1NE~5WZoLi)h%ylzrTbYQAN#wX2(BACr#8YlJ5Y~@ z$BIwRUG=yc*o2%LD@lCl7)JY|p7j`QNJU zV&gp=^n~7;tra0;VuT$Zk4WC(e>ZC57?FjeGJ7bUz^s^V*Dh}7yc=$? zsRpOnukx>S#~3@;@IUq?QEDLIx`;vu ztl^)b{8Qz5Iq&vEp7q7s0BS*CxH5Bn}>t4ZiLNtVP1z6yz#)7%({U#XSRsQVy@qbgcTFlm?m{kqL7m$GFZCJnsM=~_vDd%UFh9X!h zG!3wxR;UR@q64MceCpf~)l|ICVqoOla6=^DDUbu;cu#De?BOe8 zGyyMnW3VP63PX*Hg!oTG5$HI;B#taVAX+&Scv5(a^CMSwzRPCYFJ!1Oi&T05q7YHc zkJDhx2}mq-`d`V(e*d0K1LRyzQ}@64)8kXvRQH-|>VBv4mwvS634=?izLB5ta^GEQ z93m3QD(w~k{}+A2%0z5^EMFbGzdA`EdJ$p6429uMO-3*~B0#Xc(Ig}hy%7jogU@urT@rbdS z>iwTLV_vE^M5|O{EsJ@nFJb}Z!-i>v{REH}NBQ4dTKz(x-?!o-~F_hKJyy>CJ zL|_%5IExgkZL#a&C@dB=U~ETD_m}s%;V91);MEUNT%D_kweG10KT|qc2-r%r-XDZ7 zXEWTCIt~oa%Q-q*de1>kBwxbt)Dyu2e7;8xZO?@)za4hqrg)U|vf`szQG)^_@-}5L z{HJgfP>fdRT+IA90x#6C(vw*@dC#qZ_>*&kBNrO9RRB)_Mz7m{P*(1!Up=P*!VLds zGb;+oJR<*}54r#Oq3Fr~g#ZGJAhNN4Yp;car|tuMYjJL1z`_%9`Ad3n@D(QyB$ebq zooQo4nWHOC(g4Z>fyuM5>67zS0RRDL=)RQ9qGAdbRx8@V!d+=jMa7uRD!l#)pk2mk z)i4p+z3HjRbKQ&*p__uJc&9C}Jpj)I?M9!?sReW9>LwT7?tR!7YpvzGl*_O3LRPNL zOqJ0e(eZKe=!>DWn4}x#Q!y7I+TS0kkuz{?K>DW`LG5~T=f&=z186xu~3nVW~C94{%P(xnz zkTjeB%LWP_p@fUWm{k7$A?J_sW0RD1XFRSob{_xS%&L<6iKUJ{b5|P*Y=rJDw)fLk zXA03Bv#kL(iB>oKmlqt7jb~f=9h%y%RJ@ZnIo^LNk|TjKR46P(eN7LHYaV0K)}y@8 zLk86FFL#A>sY1{g;Z-*3l6G&4K#$LN%dRU9Z!YHV_E%8{qe{K5KHLfTT4&!>?h*tv z(t)!WGe^o<;L(BE%hdwW*T#PHTnV3FX;o}`iKqc0jI&S6&v;~*^(aT=G&A1(C-;(T z@#|tz=^mF48dGO{=!^Mk+^`UiP-{3$i9g&pee@p6?|9Ig_>;J$Lu70}QeXB#e5^J0 z{d5jEkeqP^->6~SmT&yMOy2Kf?3p)oNB->#N%NCMub;0E_{9$mH0~(P0se-gWT1Zu z%_EeV==O`w70iqta^xhd@K)ry`ZYHC4BnamhBHeT;;>e^_+~|3fYS$i^y6WLt7Bjr&)jz{xm3|M10&jz!kzsqW0Mr-Z(upd$KL7@N$x?V0Jmr;P9{aC9TYn;o)9u|Eq!WI}@f5R?Y zQNVWKg9#qdRJZ%S6=(X4>2vv&9-EE<;aKuhIa(C7V*WC-DgMoZ7{P{!17Jl9oT3@m86rl>{b1f>*?j|23T;}AFzL{l>Q*n$Qwpxnte zj+TEK)|4>*?<_aTc>tt944-&+VTQ*>Fl1@~NsdE8xe>#qL3ae$?Kgg>Vy}qGyt8eF zqMc+MVqrkrFgC5=Ne@8I&EGBXH!p?2;Oi3|68IR;qc5?GdUeN89xy(#s#!~q|2(<5 z%II%QDnm9v4=A{k$sF^_5t#BlE-qb98g3x$=FiyS%oCCi8y1vW^2e~s>Ix=I0=Ov# zm8p#X>v2xB~(1LUjZDMnHp&h z4fMLp9ESv!A}aag9D$yM1}iJ~BbSrI5!P5D#yuiEz1UGoYJUcCS^7P+@Sa~@&b_d!OOR2TRW1fGGeiPjLjC}AyDj4fX z5Hc-G4+bm_b-qf?dK1zo!>!McdaR|RtWNqcQCpM{X2r6j#_|y-IPlFfHIEok>VMQT z6jAgmpYE5r*vvduvBtxf<>3fH+_KJwB6eLoqGW5JA(riVHF8CkeG9fTy7&xM`RB)p zw^Jeu_kZvW#)i{Gr9U!VX<5SUd1|4A~}>Fzi3NAuU8nLqs;i%aGG^^ccXH8P*0+3b=~o-#^fe+?+h@jQ@;h zwbubG*hD~ihAy8q0Nw!OqZ^xnOG3Q3i$joK5==u@pACgI11}EAl7?o*8qkYS3n(?- zE28_KOQc%UQf&zn`{U`U#<#`)-DK5f2%b=YH=!F3yT8VDJ;J&X_GG?Ephbcrca%NS z3ICtN)xjLZM(LE?`Xc{?I5|I@_s{55EyN~V>0MM~GuZ&J_7-+6mQeB=i~VyJKtN!+ zwA`%rOxQ}o1CAZvClQWLCKfG8t-UN=euXmg6CUF!AYK-}x)mr-DGQ2K6VM#nmw8B1 zAuoa5*_|HF|9!G}h2#{R;?zaz{S(Q~{c7?Kx;OR0$GOs^FecRm@P1Weo0MUxkXfPr z-zYSzJ>h@EFtn^+Ej_~rkI0b-mLkmdKfMn`MaKz1ljn2C0Kni01Q1uN6c0>BRV;!f z;h$sbV}!E)dNYxp-i`wx1FMtfghQ#@V7MROu!Kiz+GTZIKH)Rzay|GA6mB!a1Ck!9t+X&dSjjCKlcb zW}D5#V(5OWGXYjO*?9&Qs}&;rd;2N0-U58buWpUUxKOmEhKk3L@V~MVP{;(rqb>*L zpawQUWD33evDEWxI~dE{us3p(YY`17U;}tB z5e$uSl%SWZ8JwVILBXZceHsTw;_=ljb7h{{oL(il`ZfUgbC~5e(w`4x-B3gGOW8m9 zkkp!-xtGF=&KG*R@@hap7$#pj9}Y93F%^WvnoYafYTl*Tqc{*+zjCfw8^`Dlg5l$z zSDPbpRTg_5sk+KXLD5 zd+H$&RrbD-xF#qUCl`zbk+VV+ceK$i}*77AbRbRZ3oyUvgX0gQ^UZ`dQ^u-XvsGaVx15w9QS5CXT zAuc61e(bFAQKf%+djR;}1X7cfkP3IEz$BhNF&P+y?Pj@qR$yZubfl+m*U; zKlmGkM+oLnLhGhs1u@XuJ0wx)QQ)cn!L^?p{k#|pq&wOUcR)Cao8|uAe1k$EKdKm; z;Il{`r&Q&(IKElpRMv&03Q-}$21NVKIO$zZDjwOqyWUa)3Wbn6cO7lG+FY=I3E;wpp<@kqQZ0Aj!@-T1)09qwjB^Qp0yTg5Tk*MNm#h-Gz z2vBxk71jY#T!qq@JLKGH!YxxxYyaHcPY6j>&(1F9=K&(F51=gr&wC5ilGg1?0t$f6 zxH|rY*^dJTho1XdfBap}1xd}71mazcrZ}AC87>C8C*s7;J5G4vKF!@7-z8jRtyoKq zpnjqLmglKgmXwN#JAhS{!KHQy>x^*}-1KD5l-!ggsabldF){Yo#6#eqbzdQ{ef!iI zExeCa3Y&YW?BKHZs|~VV@2}Far4JwgIrsGKR5NTq<_0Go;^AY@RQ!9<4XV;^Ck`7g zQh~t_CmP(6l9mG@g2k@;MOqRpTbvE(9CFP3d;NSw+` zFr1qrJR#9M;7GXeV!IH?lM+#(^tXsCG2I;{9M>|y6MRFgC{GyHon?Zk$Ji8Z$=CqZ zlVQ($)llw&cmO851A${J5S}{hMBpwbN{*VRoICk80K0(sXrPyHD+2+Y2HV%Z8WQBz z)zpE@Vu@nwnr&7zE1tTJD@|r3;#{+|L54K@Ip5AhJs5~r0`@CpVc0gbtZBsHc=mPf;4r@%-Vs}aoV@cM&NP$)tzq%if?2ckRNtoR_nM%I)CQ5DY&c` zt^4}okUxTNR1v?%(Tw@^JLdMo?alJq%dLD#R6Bxa;>tIU4tSjx#wF5c_jWU*gcN@BYzOk9u#rA*;KHva=N7ryn{>!GIbO#4K8~Cl z3QX&!5n1QKKt~<`SoaVB?m$m26i(6Qc{=xX`P&$)KGw*w#syq}!)EQzP>=&Fj!Zat zlEaW$*Vh6#XduF@__~zbdi*#nC?M6(Q`ea?9SZdWcs@{&1EmO)0_?M6PwpoIb36hd zKbBw^I|6ND0AAamC3J*DGzT&zN0g^eM-ru82YsXz)Bi z5|%3(0!m|IQ|p3%W?YrT0@GrwYyYwi$Y;l-&IJW`{v_v~g`=Ekc&^8l3n7$17&)d> zgin&ntB6?3-WF_6wHP1@0p^HRBKU>OEp?j|V6MbHJ@fVgO2&`{NAYe~p+^mX{~&GP z=bhvsYC@dKpI5#8C~qy?P&WSEJfmS zY)g=sS5i6#VrVw$<9;kDEdPMO2Hgu`>rrTM89YV!YN)t%`^m8n<4Im3(gfsztuQ~# z+&j1#Sh0|Q0SF=i_Ppt7t1>6A08Cv|&qaa&ZvfIuxS$#cKz10Ss%4@(6H$e+H~DJ^ zL=eD&DQQ6Ik_NHHt(c%b9ln~+#zew<#~?wtpqF)Khq?H_h!Wrq~;nAOB%RgChY<12`!@a7N})>yJZO3!0c8LAe2iSam(Ac*}V|amMFps{rXnTR~Pp z0npK!+9YJDEcK1i>Yjo1_J%m7HUl=R@>~e%T#XqRIbj1%GprmOMMwQVxE>lH`3)O=SCxPmDU_D-8}j4a6ERGu;{_VC z9G2v3;tf*(+b9}?SAG{YW>yWm?-yd52Q1h%QVBJSs+!WCSmQDT812$g*$xog@tLbQ zfMMzjVM__nTF9&hVBDOBXXZ6n(E2xkxdu2#0(Mr6BIhwkNc%6H*bUpDY+-o+ZdTQo zyIds%@hSqJe}<%j&QcLWwDbvUh${C&EdBhLWk8=E;50}y!zLWM#t0yoKoN7Hwt%lcqx>noV5I?l{7hPI zEaN?FNx$_0Pd$Zgy~HbH&x0HIpoN;C!7>2CR94mDkG89<9JUSrFcXG7PMyyNtcHvg z4O#+8g%uy)dNo)J4DZm$c2QH)Ra6Wm{5`-Pi-dsIX+Q`&T^&M}+I>DaaL>K}e6&P@ z%`k#!O#&77Or8nd3$$^7g%3|~U5?)0?L7_9X7V*!QgCs0Nu1?zAe}t*()nJvvrrk0iGw`5? zKmu$(JpIaOb!+<7J!xsWx~^+~^A6wf5@`WI6>Nn8AP}|`bh-$jeR zZte>{quTz#L1f3_2YMae*?L(@pb!D)>;N1T9O?XEc(%!5_453;*R5gAjJuB#M>6hy z1Z0wskn~402mjKc0>E6Cfm_Y;p<$uje4J>AXGuxPJ#lgIeMA;5Fx0EiE=Y`uifa3r zAFx9F=q$|m+z)#S8URvtAKS1ar>Y0p*LTR4Vu5i3Mx6n?*$Y^ndXD!LBP$PDd|yoY(IrbbT2bKL7pG*4I~Zc-=E~WWAap)P5v=AfxlR z%=o>(ca3>_;{jI$U`%Swt$*Eh{yx+E>ZjqPb*ye0C1qkITw~1!fAf-#NrN`HPIB6T z@V$8Pg1xcdO9YT5cYU@h`FzhDh^PP^9i0teailB@04O(~Hca8PK?*{XcNRV=$)cVK#GxuDmhT}0OAM41K^+En>c-oLL)L@IchgU_rT-^ zM(#njT!n2AjWZEjk%(Gyq#U`!V%_JM-{(7a_qYGe>zU`7=leY0&-e3vU#|fGDIy>K z!@fP?rE7n=@e76roK4Ysv3MJJzmV5HC4*|a)Dla-e!^75yZQIVO3f}E1rAfK`TnYv z)A9M@%fWjmq*jex_yD65M|$YSX-|rVyG3-4Yi!scB7m|0Bi!Ls&SU^bLI{6f-~W%p zTE6tv`bn3iSwDMw4R_A++@8IA!)Aux?_Lg0`ZfEhh~ziSbI^VCKBpLHB*W&$Tv_XF zk2>paub)B2P=d`+<*e4-%-mZh;kaU7d?{qitU3zPKqb=BH;|rb6Qrc}ID~$(7 z)zzMcyKHP}?0llJPIV2imb1@hCe>?7{U_ULOZ6^S^b`}{x(_GQU+W5M4%|t)-B^62 z90>Ypv$vx!eV^A>(Wz;s%Bd2Lh*a_b_7qOfljb|4z4ovHMp>Oq@7^nX@~^M^%M(Y1VRzCkJtmgvndL0bg<8kr$S&4cVVlbkLX zrvV{lwG^0e5+_65xG&tQuSCoxo%jwq#vN#5rfFaW!vfxS*K^@AxXVsxD>U*NE)8&Z zaPhu){@|v;`Oj|Zr>w9%^in|KB@^Up%;`CV=aK(p5<)8bG4yWfo~8V#)11VKH=U=- z#!Ei;rT-$0U+sz^)KNmPS0T!@g>hnEIP?5kddSc9)61BtWbS+vZE*C&vAy!bT8kGt z{a41{?O+2_PK%yD6Gr`AI^N;>R2O&6gf?hdfRVp`{W{yOMlfi-!x!wrnYpT(FSSi- zi$w_g;ykyYg){YsuCTtJ-}6EpUU#)uCWC*}vuaW$ZR`7;kEOj$rLWh?#V@zn9)l#u zU@F=n-*{v+>>@}6(4AE{r1={~htHQNNJBfmbm`JnH6D-+snDxuu2uPtAI?*=e&5nn z2z?-z%En6H`~p8Ag(AwVx(fB z+lTvYcn}#Hj_t~)c777$dmDaN&^!zO~tJ1b>mY;?45%$Doj zdA;36nseufIc)v5ARshJY!(z3i(*>Z`W4@2<(Eh{T^rA%a&71;sGEcQS^D6Jt<&+o zxpyf~KXNO5>g}0w`~Q_t_(GQO4YGp~o4ALyzB|5Lc1V*Q`+XLkq6>xj@#Y2RpDMdA z^ZyM1Lz#=$xOH>R?fos2TyyKi&-CHd5$i|1!V!oen-4k<-khmgy?%dEqHHh~L+DTi z-2vQ5JCLmT*X0i5v}k-;R~)(0ThqU#RXv}Wv>bL4`vA;3fGm>@Z=wOAx}ChJgV5TW zDBrW>yu^NkE%)XMn04|y19O!b#a92eW06DC}TNJ`!(DC9t-Iq`^nj2@{_Bn zL3@@ylwO{ms$ozOEi@^U5ym=rr}=uQo|QR{c@;2CSJe#E0l=)OUoI0x{5B`SVJc23 z@h!Xeo+3AG+_tFnx8AK2V3MT_95ucK0w-9~zcrjCS8~SPdY%&hKxQ+t@(f?aB}Wu@ zT+GHIN_Z-RqC##K$NL}MO@RHD59`ooq!^9~ULP5GFU~0(lg^`J6ll`G0TFm@jET)M z6(ztFg3ObVp<&^Yi^21*mYYLy31Dt~0(vC8u6}MPhM$xv$?g6rNJmML@M(7^=vs?F zbXlLlLn%M>U2qn$PGhI|bnewSW)jd;4FOWZCZwOdS?NZ`&^pU#X)bsm6A1fO?FSWe z==s+yE>a+yFg2UxSbcFj5~QI^N#a*!9W=}^_`S(cUk?gN{}59V+)|`CTSts-2Oyt9 zjv$lyH}=iFgPa$#xl3jB$vu3CJ*X)XefC2X2T6wdQ5@1W&V#GkAMK~%Akjrl}*>n zD(!43oLTzx{M+B8wIQ%GajurZVo-6}iU9?>X_P~G|Qu4&{%+{iVV3O9| zZ1haHJ1{Q5KXY!+=h|!moDCAJ80ZiLv^?D+UBwBZ7?|_@zr=`%PSqVsJvkefx;pUw zux+KUZ35PT5m8KG$n8gGIG{78YGvG3M@#~|2jWb$mb}}ra#x@{V*Rr4e3{LiM?_)@ z^kn>Io9HH~S{!YFUzIU6XTqNF2UA(W54sSG8j5_4ntdqX!semg-rl?@?X|_vR(F`V zEd2UN9N|97T3VIke|8kEXfJ<#Xxn%>BNP+Nb7^0}rHg;P5)PQ*EcEnf!fDrs1bPa@ zaZX_v3FjJg&VDlfD}cU_0I8SDkEwsSs0`)}-i%kp{G@RyRJnXsk?;-xC2(^VdIGqm z+Dij*zZ6R2>;%$5D8eo;NQEQP9+YbUdvclQaEbR$mCEmSHN2kEay*Oo3I1xV!7*O_!)biI`h( z7dwX-An&z6(1qx^0ua_pC(D79WH2^i0QVvYG2)Qu**U8RgApaDqJ>-?M%)P3rf0K{ za;n0&$FXd8$HS4AMW$XWgJw~w;Fgq{rjucRqQN$W#rm)A-sC?1so09!xm&$c3K26Y zxmLk{s$Kp7`Hg+<-R$UK8SY~3RADNoA?T5N8ZvZ{;yZBW09k|(eu4HFG-WU?oR-!& zD^eknD8=IqzF*4n>z|vyIy;`rSz^~3D80Vd6EJuBNwn~8CF@XNEhj`g<+tCdIUlg7 z&L<#tAvTr<>wrIwd2b7eTS;LzeRcN^&wVdZ1{loEs7mw**wgLQWCVklXwE+xuKA zASZXinEVtHjD^Zz62X-r=ae>fPzmH_`MR7sL2(hB!Y$Cf(40fG3IkgCh8UeTJAD*K zfFvSW0wxqBcnIN*QrT>ae?BThFo;ip@uH@aT6E6ln>^5(B(2NaL%zJx`5C>knW&DerG%{QWNH7OLu#6YB=Y+KmjEpj)JSGde$hTkf~ zWzn^U016eLpwR=15MUVM|8A>=oAIwagu`+M#iA`Y{Lo1Bx}4@2|8QG8Emp@oDcjy8 z}tR`hfBe@3mkcqDUhAV_G%r09o+{tu!s4{PLE&LO3IY& zar5W4O1yZvYW?);x6q^%0Hsip4Fy#lx5{@FXd$=FM(rKh6BLX{ZNH(UXP4dbirH%1 z*lkSo?uEd}G!$eZTY%?6`J)^~>*~`iyyx3dS)PqTv}4=xDr-MkQlPqCB@5pH|DFOb zJo_Rj<0GB-9!fx@4?G$LwRf@JsQ;g{E^d4M$pvn$eGq3KDVH`{|56rBTTsiR8Zpx! z)Z4N&$^5X8&d8a?+Zmv;;8P9QXyP9C5dqT~dm z4J~%b=Sw($5XTw*hZvsNq9-_@W-+a1ZfLZA8l{>v3bjI1F6&bW0bzfA`^*_KceY`d zc<^+*v_NCBysQy%#&XQ?KNU-SBrBIA;q1H@6*=Q!AOt)OZ8Bsr;1m3de^wy!Nv*q@ z+kz#>R{WYv4Epnl`!4@H6uy8fP0}`)LCA7f7QV`~(GZ?bPcY+%Me{Ru$vI>&B_ZC| z^F!cq6}5cG-e2)EK_p?e_}F7Z|J?rspWJ(2hCKCMDj;smekUt1#Cl{zG&CW{^5Qt~ z#^h?#W9{K#i5Wz`|Ll1cwInicZSZZaC8?^nsg>sCc<0KZMF30V6_qtl$!uOfLG_#X zlS&)SkCH+30*Cl68fXjNVp_$VMdAH$AQhgRcZYgo$bcmKcwVEa+R3pZij9yt1T)B1 zFfmWqhvSj14OoF{(jd(N7t_2hgo58s-Y=A0#!m?|wQ_+Uy1+^}&TndiiUgsOQb?$z z%+`*MYwX+7J`n*rhdF0ooFEfrMTNxWcf^T5VqaF=sCa`mu5$?HdmTF~L*)AY>w2BU zz+GZELmQA+ph5)2@IqnnOUSd=6AX>d{<+>4W}i2rR@$INOzgn+O{oax7H-fJH2upo z$(c6Zh?T43tw(bd0p1HIix5PomRR-H>#wIp#o{9JQ7N~>%iymgW^}HCVb~8^%}Ymr z?x&Hh@J)!Jpgpx1=DCe?uj$FWkh1%b<5Xffmx6A6#xhs7hI2EpgE|o;`KV1S8YZ$% zR>0$+kr@WPJP`t#65=zR|1Uk>0X$7k(F~K{2Tu~6P2~lB5V013w;6a`H}jJbF@X*V z7X^8X*pzG}A(kWmFj5V^)~^8;o_UMs=q_kK>#Zr5sVwbj-T_}R1m4;u+(LX-9$%!1G~Xc|Eyk~&V^h51Ez*R AUjP6A literal 0 HcmV?d00001 diff --git a/source-code/source/plugins/Launcher/Launcher.vcxproj b/source-code/source/plugins/Launcher/Launcher.vcxproj index fa9e0e8..edcfae2 100644 --- a/source-code/source/plugins/Launcher/Launcher.vcxproj +++ b/source-code/source/plugins/Launcher/Launcher.vcxproj @@ -109,6 +109,7 @@ + @@ -127,6 +128,7 @@ + diff --git a/source-code/source/plugins/Launcher/SkinnedMessageBox.h b/source-code/source/plugins/Launcher/SkinnedMessageBox.h index f78d298..cb7af5d 100644 --- a/source-code/source/plugins/Launcher/SkinnedMessageBox.h +++ b/source-code/source/plugins/Launcher/SkinnedMessageBox.h @@ -275,11 +275,16 @@ private: ref class SkinnedMessageBoxForm : Form } else if (icon == MessageBoxIcon::Information) // also Asterisk { - Drawing::Icon^ infoicon = gcnew Drawing::Icon(SystemIcons::Information, iconsize, iconsize); + /*Drawing::Icon^ infoicon = gcnew Drawing::Icon(SystemIcons::Information, iconsize, iconsize); iconPB->Image = infoicon->ToBitmap(); iconPB->AccessibleDescription = "Information"; //this.Icon = SystemIcons.Question; - System::Media::SystemSounds::Asterisk->Play(); + System::Media::SystemSounds::Asterisk->Play();*/ + + iconPB->Image = (Image^)(ResMgr->GetObject("Help")); + iconPB->AccessibleDescription = "Question"; + //this.Icon = SystemIcons.Question; + System::Media::SystemSounds::Question->Play(); } else { diff --git a/source-code/source/plugins/Launcher/SkinnedMessageBox.resx b/source-code/source/plugins/Launcher/SkinnedMessageBox.resx index be0a343..f2e5eae 100644 --- a/source-code/source/plugins/Launcher/SkinnedMessageBox.resx +++ b/source-code/source/plugins/Launcher/SkinnedMessageBox.resx @@ -121,6 +121,9 @@ FeelsThinkMan.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + Help.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + PokeSnarf4xd.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/source-code/source/plugins/Launcher/composition.h b/source-code/source/plugins/Launcher/composition.h new file mode 100644 index 0000000..0f368ae --- /dev/null +++ b/source-code/source/plugins/Launcher/composition.h @@ -0,0 +1,99 @@ +#pragma once +#include + +enum AccentState { + ACCENT_DISABLED = 0, + ACCENT_ENABLE_GRADIENT = 1, + ACCENT_ENABLE_TRANSPARENTGRADIENT = 2, + ACCENT_ENABLE_BLURBEHIND = 3, + ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, + ACCENT_ENABLE_HOSTBACKDROP = 5, + ACCENT_INVALID_STATE = 6 +}; + +enum WindowCompositionAttribute { + WCA_ACCENT_POLICY = 19, + WCA_USEDARKMODECOLORS = 26 +}; + +struct AccentPolicy { + AccentState accentState; + int accentFlags; + int gradientColor; + int animationId; +}; + +struct WindowCompositionAttributeData { + WindowCompositionAttribute attribute; + PVOID pData; + ULONG dataSize; +}; + +bool setBlur(HWND hWnd, AccentState accentState) +{ + HKEY CurrentVersion; + auto result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &CurrentVersion); + if (result == ERROR_SUCCESS) + { + DWORD DataSize = 32; + WCHAR* DataPtr = (WCHAR*)malloc(DataSize); + memset(DataPtr, 0, DataSize); + bool queryBuild = RegQueryValueEx(CurrentVersion, L"CurrentBuild", NULL, NULL, (LPBYTE)DataPtr, &DataSize) == ERROR_SUCCESS; + RegCloseKey(CurrentVersion); + if (queryBuild) + { + int BuildNum = _wtoi(DataPtr); + //MessageBox::Show(BuildNum.ToString()); + if (BuildNum < 19042) return 0; + } + else return 0; + } + else return 0; + + const HINSTANCE hModule_user32 = LoadLibrary(TEXT("user32.dll")); + if (hModule_user32) + { + typedef BOOL(WINAPI* p_SetWindowCompositionAttribute)(HWND, WindowCompositionAttributeData*); + + const p_SetWindowCompositionAttribute SetWindowCompositionAttribute = (p_SetWindowCompositionAttribute)GetProcAddress(hModule_user32, "SetWindowCompositionAttribute"); + + bool result = false; + + if (SetWindowCompositionAttribute) + { + AccentPolicy policy; + policy.accentState = accentState; + policy.accentFlags = 2; + policy.gradientColor = 0x01000000; + policy.animationId = 0; + + WindowCompositionAttributeData data; + data.attribute = WCA_ACCENT_POLICY; + data.pData = &policy; + data.dataSize = sizeof(AccentPolicy); + + result = SetWindowCompositionAttribute(hWnd, &data); + } + FreeLibrary(hModule_user32); + + return result; + } +} + +void setDarkTheme(HWND hWnd, bool dark=true) +{ + const HINSTANCE hModule_dwmapi = LoadLibrary(TEXT("dwmapi.dll")); + if (hModule_dwmapi) + { + typedef BOOL(WINAPI* p_DwmSetWindowAttribute)(HWND, DWORD, LPCVOID, DWORD); + const p_DwmSetWindowAttribute DwmSetWindowAttribute = (p_DwmSetWindowAttribute)GetProcAddress(hModule_dwmapi, "DwmSetWindowAttribute"); + + if (DwmSetWindowAttribute) + { + LONG useDarkModeColors = dark; + if(DwmSetWindowAttribute(hWnd, 20, &useDarkModeColors, sizeof(useDarkModeColors))) + DwmSetWindowAttribute(hWnd, 19, &useDarkModeColors, sizeof(useDarkModeColors)); + } + FreeLibrary(hModule_dwmapi); + } +} diff --git a/source-code/source/plugins/Launcher/framework.h b/source-code/source/plugins/Launcher/framework.h index 902b284..5f1ca80 100644 --- a/source-code/source/plugins/Launcher/framework.h +++ b/source-code/source/plugins/Launcher/framework.h @@ -140,7 +140,7 @@ static std::vector getScreenRatesVec(std::vector &screenModes) { std::vector screenModes = getScreenModes(); -DropdownOption* DisplayModeDropdown = new DropdownOption(L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 1, std::vector({ L"Windowed", L"Popup (recommended)", L"Exclusive", L"Failsafe" })); +DropdownOption* DisplayModeDropdown = new DropdownOption(L"display", RESOLUTION_SECTION, CONFIG_FILE, L"Display:", L"Sets the window/screen mode.", 1, std::vector({ 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); ConfigOptionBase* screenResolutionArray[] = { @@ -159,6 +159,7 @@ ConfigOptionBase* internalResolutionArray[] = { }; ConfigOptionBase* graphicsArray[] = { + new DropdownOption(L"model", L"GPU", CONFIG_FILE, L"NVIDIA GPU:", L"Select your NVIDIA GPU's architecture to apply the necessary workarounds.\n\nNOTE: Automatic detection does not currently work on GNU/Linux.", -1, std::vector({ L"Automatic", L"Kepler", L"Maxwell", L"Turing", L"Ampere" }), -1), new BooleanOption(L"TAA", GRAPHICS_SECTION, CONFIG_FILE, L"TAA", L"Temporal Anti-Aliasing", true, false), new BooleanOption(L"MLAA", GRAPHICS_SECTION, CONFIG_FILE, L"MLAA", L"Morphological Anti-Aliasing", true, false), new DropdownOption(L"MAG", GRAPHICS_SECTION, CONFIG_FILE, L"Filter:", L"Image filter.\n\nBilinear: default filter\nNearest-neighbour: sharpest, but blocky\nSharpen: sharp filter\nCone: smooth filter", 0, std::vector({ L"Bilinear", L"Nearest-neighbour", L"Sharpen", L"Cone" })), @@ -180,14 +181,17 @@ ConfigOptionBase* optionsArray[] = { 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"stereo", PATCHES_SECTION, CONFIG_FILE, L"Stereo", L"Use 2 channels instead of 4 (when not using DivaSound).", true, false), + new OptionMetaSeparator(), new OptionMetaSpacer(8), new DropdownOption(L"quick_start", PATCHES_SECTION, CONFIG_FILE, L"Quick Start:", L"Skip one or more menus.", 1, std::vector({ 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 OptionMetaSeparator(), new OptionMetaSpacer(8), 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 OptionMetaSeparator(), new OptionMetaSpacer(8), new DropdownOption(L"force_mouth", PATCHES_SECTION, CONFIG_FILE, L"Mouth Type:", L"Change the mouth animations.", 0, std::vector({ L"Default", L"Force PDA", L"Force FT" })), @@ -196,12 +200,13 @@ ConfigOptionBase* optionsArray[] = { 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 BooleanOption(L"sing_missed", PATCHES_SECTION, CONFIG_FILE, L"Sing Missed", L"Sing missed notes.", false, false), + new OptionMetaSeparator(), new OptionMetaSpacer(8), new BooleanOption(L"hide_volume", PATCHES_SECTION, CONFIG_FILE, L"Hide Volume Buttons", L"Hide the volume and SE control buttons.", false, false), new BooleanOption(L"no_pv_ui", PATCHES_SECTION, CONFIG_FILE, L"Disable PV UI", L"Remove the photo controls during PV playback.", false, false), new BooleanOption(L"hide_pv_watermark", PATCHES_SECTION, CONFIG_FILE, L"Hide PV Watermark", L"Hide the watermark that's usually shown in PV viewing mode.", false, false), - new DropdownOption(L"status_icons", PATCHES_SECTION, CONFIG_FILE, L"Network Status Icons:", L"Set the state of card reader and network status icons.", 3, std::vector({ L"Default", L"Hidden", L"Error", L"OK", L"Partial OK" })), + new DropdownOption(L"status_icons", PATCHES_SECTION, CONFIG_FILE, L"Top-Right Corner Icons:", L"Set the state of card reader and network status icons.", 3, std::vector({ L"Default", L"Hidden", L"Error", L"OK", L"Partial OK" })), new BooleanOption(L"no_lyrics", PATCHES_SECTION, CONFIG_FILE, L"Disable Lyrics", L"Disable showing lyrics.", false, false), new BooleanOption(L"no_error", PATCHES_SECTION, CONFIG_FILE, L"Disable Error Banner", L"Disable the error banner on the attract screen.", true, false), new BooleanOption(L"hide_freeplay", PATCHES_SECTION, CONFIG_FILE, L"Hide \"FREE PLAY\"/\"CREDIT(S)\"", L"Hide the \"FREE PLAY\"/\"CREDIT(S)\" text.", false, false), @@ -209,37 +214,49 @@ ConfigOptionBase* optionsArray[] = { new BooleanOption(L"pdloadertext", PATCHES_SECTION, CONFIG_FILE, L"PD Loader FREE PLAY", L"Show \"PD Loader\" instead of \"FREE PLAY\".", true, false), new BooleanOption(L"no_timer", PATCHES_SECTION, CONFIG_FILE, L"Freeze Timer", L"Disable the timer.", true, false), new BooleanOption(L"no_timer_sprite", PATCHES_SECTION, CONFIG_FILE, L"Disable Timer Sprite", L"Disable the timer sprite.", true, false), + new OptionMetaSeparator(), 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 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 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 OptionMetaSeparator(), new OptionMetaSpacer(8), new BooleanOption(L"autopause", KEYCONFIG_SECTION, KEYCONFIG_FILE, L"Pause Automatically", L"Pause when focus is lost.", true, true), + 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_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 OptionMetaSpacer(8), new BooleanOption(L"custom_patches", PATCHES_SECTION, CONFIG_FILE, L"Enable Custom Patches", L"Enables all custom patches.", true, 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 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 OptionMetaSpacer(8), + + 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"no_gpu_dialog", LAUNCHER_SECTION, CONFIG_FILE, L"Disable GPU Warning", L"Disables the warning dialog for unsupported GPUs.", false, false), }; ConfigOptionBase* playerdataArray[] = { diff --git a/source-code/source/plugins/Launcher/ui.h b/source-code/source/plugins/Launcher/ui.h index e273df7..4600ba5 100644 --- a/source-code/source/plugins/Launcher/ui.h +++ b/source-code/source/plugins/Launcher/ui.h @@ -9,6 +9,7 @@ #include "PluginConfig.h" #include "GPUModel.h" #include "WineVer.h" +#include "composition.h" namespace Launcher { @@ -20,6 +21,8 @@ namespace Launcher { using namespace System::Drawing; using namespace msclr::interop; + HWND hWnd; + /// /// Summary for ui /// @@ -29,7 +32,9 @@ namespace Launcher { ui(void) { InitializeComponent(); - this->button_Discord->Cursor = Cursors::Hand; + + hWnd = (HWND)Control::Handle.ToPointer(); + this->ClientSize = Drawing::Size(444, 323); TabPadding^ tabpad = gcnew TabPadding(tabControl); @@ -94,6 +99,7 @@ namespace Launcher { option->hasChanged = OptionsConfigChanged; detailsY += option->AddToPanel(panel_Details, 12, detailsY, toolTip1); } + trackBar_LagCompensation->Value = GetIniInt(GRAPHICS_SECTION, L"lag_compensation", 0, CONFIG_FILE); this->panel_Details->ResumeLayout(false); this->panel_Details->PerformLayout(); @@ -178,8 +184,15 @@ namespace Launcher { int argc = 1; char* argv[1] = { (char*)"" }; + + updateLagCompMsec(); + + updateStyle(); + + glutInit(&argc, argv); int window = glutCreateWindow("glut"); // a context must be created to use glGetString + glutHideWindow(); String^ vendor = gcnew String((char*)glGetString(GL_VENDOR)); vendor = vendor->Replace(" Corporation", ""); // this is useless.. remove it to help ensure the GPU type line fits @@ -249,13 +262,13 @@ namespace Launcher { { this->labelGPU->Text += "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."; - this->labelGPU->LinkColor = System::Drawing::Color::Yellow; + this->labelGPU->LinkColor = System::Drawing::Color::Teal; } else if (gpuModel->StartsWith("GK")) { this->labelGPU->Text += "Issues: None."; GPUIssueText = "Your GPU should have no issues running the game."; - this->labelGPU->LinkColor = System::Drawing::Color::Lime; + this->labelGPU->LinkColor = System::Drawing::Color::LightBlue; } else if (gpuModel->StartsWith("GF")) { @@ -270,7 +283,7 @@ namespace Launcher { { this->labelGPU->Text += "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."; - this->labelGPU->LinkColor = System::Drawing::Color::Lime; + this->labelGPU->LinkColor = System::Drawing::Color::Teal; } } else if (version[0] >= '4' && gpuModel->Length > 0 && !gpuModel->StartsWith("Unk") && !gpuModel->StartsWith("Oth")) @@ -313,8 +326,101 @@ namespace Launcher { delete components; } } + + void OnPaintBackground(PaintEventArgs e) override + { + } + + /*property System::Windows::Forms::CreateParams^ CreateParams + { + virtual System::Windows::Forms::CreateParams^ get() override + { + System::Windows::Forms::CreateParams^ params = Form::CreateParams; + params->ExStyle |= 0x00200000L; + + return params; + } + }*/ + + void updateLagCompMsec() + { + this->groupBox_Lag->Text = "Lag Compensation (" + this->trackBar_LagCompensation->Value * 10 + " msec)"; + } + + void updateStyle() + { + int nDarkLauncher = GetPrivateProfileIntW(LAUNCHER_SECTION, L"dark_launcher", FALSE, CONFIG_FILE); + int nAcrylicLauncher = GetPrivateProfileIntW(LAUNCHER_SECTION, L"acrylic_blur", FALSE, CONFIG_FILE); + + bool useAcrylic = nAcrylicLauncher && setBlur(hWnd, AccentState::ACCENT_ENABLE_ACRYLICBLURBEHIND); + + Color colourBg, colourBg2, colourFg; + + if (nDarkLauncher) + { + setDarkTheme(hWnd); + colourFg = Color::White; + colourBg = Color::FromArgb(64, 64, 64); // tabControl + colourBg2 = Color::Black; + } + else + { + setDarkTheme(hWnd, false); + colourFg = Color::FromArgb(64, 64, 64); + colourBg = Color::White; // tabControl + colourBg2 = Color::FromArgb(242, 242, 242); + } + + if (useAcrylic) + { + colourBg2 = Color::FromArgb(255, 255, 255); + this->button_Discord->BackColor = colourBg2; + this->button_github->BackColor = colourBg2; + this->button_Wiki->BackColor = colourBg2; + } + else + { + this->button_Discord->BackColor = Color::Transparent; + this->button_github->BackColor = Color::Transparent; + this->button_Wiki->BackColor = Color::Transparent; + } + + this->tabPage_Resolution->BackColor = colourBg; + this->tabPage_Resolution->ForeColor = colourFg; + this->tabPage_Patches->BackColor = colourBg; + this->tabPage_Patches->ForeColor = colourFg; + this->tabPage_Playerdata->BackColor = colourBg; + this->tabPage_Playerdata->ForeColor = colourFg; + this->tabPage_Plugins->BackColor = colourBg; + this->tabPage_Plugins->ForeColor = colourFg; + this->tabPage_Components->BackColor = colourBg; + this->tabPage_Components->ForeColor = colourFg; + this->creditsTextBox->BackColor = colourBg; + this->creditsTextBox->ForeColor = colourFg; + + this->tabControl->BackColor = colourBg; + this->tabControl->ForeColor = colourFg; + + this->BackColor = colourBg2; + + this->button_Launch->BackColor = colourBg; + this->button_Launch->ForeColor = colourFg; + this->button_Apply->BackColor = colourBg; + this->button_Apply->ForeColor = colourFg; + + this->labelGPU->ForeColor = colourFg; + + this->groupBox_Details->ForeColor = colourFg; + this->groupBox_InternalRes->ForeColor = colourFg; + this->groupBox_Lag->ForeColor = colourFg; + this->groupBox_ScreenRes->ForeColor = colourFg; + } + + private: + + private: System::Windows::Forms::Button^ button_Launch; - private: System::Windows::Forms::Button^ button_Help; + private: System::Windows::Forms::GroupBox^ groupBox_ScreenRes; private: System::Windows::Forms::TabControl^ tabControl; private: System::Windows::Forms::TabPage^ tabPage_Resolution; @@ -333,7 +439,7 @@ namespace Launcher { private: System::Windows::Forms::Panel^ panel_ScreenRes; private: System::Windows::Forms::Panel^ panel_IntRes; private: System::Windows::Forms::LinkLabel^ labelGPU; - private: System::Windows::Forms::Button^ button_Apply; + private: System::Windows::Forms::TabPage^ tabPage_Credits; @@ -341,6 +447,14 @@ private: System::Windows::Forms::TextBox^ creditsTextBox; private: System::Windows::Forms::GroupBox^ groupBox_Details; private: System::Windows::Forms::Panel^ panel_Details; private: System::Windows::Forms::Panel^ panel_Custom; +private: System::Windows::Forms::Button^ button_Apply; +private: System::Windows::Forms::GroupBox^ groupBox_Lag; +private: System::Windows::Forms::TrackBar^ trackBar_LagCompensation; +private: System::Windows::Forms::Button^ button_Wiki; + + + + @@ -375,11 +489,12 @@ private: System::Windows::Forms::Panel^ panel_Custom; this->components = (gcnew System::ComponentModel::Container()); System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(ui::typeid)); this->button_Launch = (gcnew System::Windows::Forms::Button()); - this->button_Help = (gcnew System::Windows::Forms::Button()); this->groupBox_ScreenRes = (gcnew System::Windows::Forms::GroupBox()); this->panel_ScreenRes = (gcnew System::Windows::Forms::Panel()); this->tabControl = (gcnew System::Windows::Forms::TabControl()); this->tabPage_Resolution = (gcnew System::Windows::Forms::TabPage()); + this->groupBox_Lag = (gcnew System::Windows::Forms::GroupBox()); + this->trackBar_LagCompensation = (gcnew System::Windows::Forms::TrackBar()); this->groupBox_Details = (gcnew System::Windows::Forms::GroupBox()); this->panel_Details = (gcnew System::Windows::Forms::Panel()); this->labelGPU = (gcnew System::Windows::Forms::LinkLabel()); @@ -400,9 +515,12 @@ private: System::Windows::Forms::Panel^ panel_Custom; this->button_github = (gcnew System::Windows::Forms::Button()); this->toolTip1 = (gcnew System::Windows::Forms::ToolTip(this->components)); this->button_Apply = (gcnew System::Windows::Forms::Button()); + this->button_Wiki = (gcnew System::Windows::Forms::Button()); this->groupBox_ScreenRes->SuspendLayout(); this->tabControl->SuspendLayout(); this->tabPage_Resolution->SuspendLayout(); + this->groupBox_Lag->SuspendLayout(); + (cli::safe_cast(this->trackBar_LagCompensation))->BeginInit(); this->groupBox_Details->SuspendLayout(); this->groupBox_InternalRes->SuspendLayout(); this->tabPage_Patches->SuspendLayout(); @@ -411,57 +529,29 @@ private: System::Windows::Forms::Panel^ panel_Custom; this->tabPage_Plugins->SuspendLayout(); this->tabPage_Credits->SuspendLayout(); this->SuspendLayout(); - // - // button_Launch - // + this->button_Launch->BackColor = System::Drawing::Color::White; this->button_Launch->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control; this->button_Launch->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->button_Launch->Location = System::Drawing::Point(4, 496); - this->button_Launch->Margin = System::Windows::Forms::Padding(4); + this->button_Launch->Location = System::Drawing::Point(172, 389); this->button_Launch->Name = L"button_Launch"; - this->button_Launch->Size = System::Drawing::Size(102, 34); + this->button_Launch->Size = System::Drawing::Size(217, 23); this->button_Launch->TabIndex = 20; this->button_Launch->Text = L"Launch"; + this->button_Launch->UseVisualStyleBackColor = false; this->button_Launch->Click += gcnew System::EventHandler(this, &ui::Button_Launch_Click); - // - // button_Help - // - this->button_Help->DialogResult = System::Windows::Forms::DialogResult::Cancel; - this->button_Help->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control; - this->button_Help->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->button_Help->Location = System::Drawing::Point(114, 496); - this->button_Help->Margin = System::Windows::Forms::Padding(4); - this->button_Help->Name = L"button_Help"; - this->button_Help->Size = System::Drawing::Size(104, 34); - this->button_Help->TabIndex = 21; - this->button_Help->Text = L"User guide"; - this->button_Help->Click += gcnew System::EventHandler(this, &ui::Button_Help_Click); - // - // groupBox_ScreenRes - // this->groupBox_ScreenRes->Controls->Add(this->panel_ScreenRes); this->groupBox_ScreenRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->groupBox_ScreenRes->ForeColor = System::Drawing::Color::White; - this->groupBox_ScreenRes->Location = System::Drawing::Point(8, 9); - this->groupBox_ScreenRes->Margin = System::Windows::Forms::Padding(4); + this->groupBox_ScreenRes->Location = System::Drawing::Point(5, 6); this->groupBox_ScreenRes->Name = L"groupBox_ScreenRes"; - this->groupBox_ScreenRes->Padding = System::Windows::Forms::Padding(4); - this->groupBox_ScreenRes->Size = System::Drawing::Size(395, 170); + this->groupBox_ScreenRes->Size = System::Drawing::Size(263, 113); this->groupBox_ScreenRes->TabIndex = 10; this->groupBox_ScreenRes->TabStop = false; this->groupBox_ScreenRes->Text = L"Screen Resolution"; - // - // panel_ScreenRes - // this->panel_ScreenRes->AutoScroll = true; - this->panel_ScreenRes->Location = System::Drawing::Point(8, 28); - this->panel_ScreenRes->Margin = System::Windows::Forms::Padding(4); + this->panel_ScreenRes->Location = System::Drawing::Point(5, 19); this->panel_ScreenRes->Name = L"panel_ScreenRes"; - this->panel_ScreenRes->Size = System::Drawing::Size(379, 134); + this->panel_ScreenRes->Size = System::Drawing::Size(253, 89); this->panel_ScreenRes->TabIndex = 0; - // - // tabControl - // this->tabControl->Controls->Add(this->tabPage_Resolution); this->tabControl->Controls->Add(this->tabPage_Patches); this->tabControl->Controls->Add(this->tabPage_Playerdata); @@ -469,288 +559,242 @@ private: System::Windows::Forms::Panel^ panel_Custom; this->tabControl->Controls->Add(this->tabPage_Plugins); this->tabControl->Controls->Add(this->tabPage_Credits); this->tabControl->Location = System::Drawing::Point(0, 0); - this->tabControl->Margin = System::Windows::Forms::Padding(4); this->tabControl->Name = L"tabControl"; this->tabControl->SelectedIndex = 0; - this->tabControl->Size = System::Drawing::Size(777, 489); + this->tabControl->Size = System::Drawing::Size(560, 384); this->tabControl->TabIndex = 10; - // - // tabPage_Resolution - // - this->tabPage_Resolution->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), - static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Resolution->BackColor = System::Drawing::Color::White; this->tabPage_Resolution->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch; + this->tabPage_Resolution->Controls->Add(this->groupBox_Lag); this->tabPage_Resolution->Controls->Add(this->groupBox_Details); this->tabPage_Resolution->Controls->Add(this->labelGPU); this->tabPage_Resolution->Controls->Add(this->groupBox_InternalRes); this->tabPage_Resolution->Controls->Add(this->groupBox_ScreenRes); - this->tabPage_Resolution->Location = System::Drawing::Point(4, 29); - this->tabPage_Resolution->Margin = System::Windows::Forms::Padding(4); + this->tabPage_Resolution->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), + static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Resolution->Location = System::Drawing::Point(4, 22); this->tabPage_Resolution->Name = L"tabPage_Resolution"; - this->tabPage_Resolution->Padding = System::Windows::Forms::Padding(4); - this->tabPage_Resolution->Size = System::Drawing::Size(769, 456); + this->tabPage_Resolution->Padding = System::Windows::Forms::Padding(3); + this->tabPage_Resolution->Size = System::Drawing::Size(552, 358); this->tabPage_Resolution->TabIndex = 0; this->tabPage_Resolution->Text = L"Graphics"; - // - // groupBox_Details - // + this->groupBox_Lag->Controls->Add(this->trackBar_LagCompensation); + this->groupBox_Lag->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + this->groupBox_Lag->Location = System::Drawing::Point(5, 282); + this->groupBox_Lag->Name = L"groupBox_Lag"; + this->groupBox_Lag->Size = System::Drawing::Size(263, 70); + this->groupBox_Lag->TabIndex = 21; + this->groupBox_Lag->TabStop = false; + this->groupBox_Lag->Text = L"Lag Compensation"; + this->trackBar_LagCompensation->Location = System::Drawing::Point(7, 20); + this->trackBar_LagCompensation->Maximum = 50; + this->trackBar_LagCompensation->Name = L"trackBar_LagCompensation"; + this->trackBar_LagCompensation->Size = System::Drawing::Size(250, 45); + this->trackBar_LagCompensation->TabIndex = 0; + this->trackBar_LagCompensation->ValueChanged += gcnew System::EventHandler(this, &ui::trackBar_LagCompensation_ValueChanged); this->groupBox_Details->Controls->Add(this->panel_Details); this->groupBox_Details->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->groupBox_Details->ForeColor = System::Drawing::Color::White; - this->groupBox_Details->Location = System::Drawing::Point(411, 9); - this->groupBox_Details->Margin = System::Windows::Forms::Padding(4); + this->groupBox_Details->Location = System::Drawing::Point(274, 6); this->groupBox_Details->Name = L"groupBox_Details"; - this->groupBox_Details->Padding = System::Windows::Forms::Padding(4); - this->groupBox_Details->Size = System::Drawing::Size(350, 439); + this->groupBox_Details->Size = System::Drawing::Size(272, 346); this->groupBox_Details->TabIndex = 11; this->groupBox_Details->TabStop = false; this->groupBox_Details->Text = L"Details"; - // - // panel_Details - // this->panel_Details->AutoScroll = true; - this->panel_Details->Location = System::Drawing::Point(8, 28); - this->panel_Details->Margin = System::Windows::Forms::Padding(4); + this->panel_Details->Location = System::Drawing::Point(5, 19); this->panel_Details->Name = L"panel_Details"; - this->panel_Details->Size = System::Drawing::Size(334, 403); + this->panel_Details->Size = System::Drawing::Size(261, 321); this->panel_Details->TabIndex = 0; - // - // labelGPU - // this->labelGPU->AutoSize = true; - this->labelGPU->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(80)), static_cast(static_cast(24)), - static_cast(static_cast(24)), static_cast(static_cast(24))); - this->labelGPU->Location = System::Drawing::Point(8, 314); - this->labelGPU->MinimumSize = System::Drawing::Size(395, 20); + this->labelGPU->BackColor = System::Drawing::Color::Transparent; + this->labelGPU->ForeColor = System::Drawing::Color::Black; + this->labelGPU->Location = System::Drawing::Point(5, 209); + this->labelGPU->Margin = System::Windows::Forms::Padding(2, 0, 2, 0); + this->labelGPU->MinimumSize = System::Drawing::Size(263, 13); this->labelGPU->Name = L"labelGPU"; - this->labelGPU->Size = System::Drawing::Size(395, 20); + this->labelGPU->Size = System::Drawing::Size(263, 13); this->labelGPU->TabIndex = 21; this->labelGPU->TextAlign = System::Drawing::ContentAlignment::MiddleLeft; - // - // groupBox_InternalRes - // this->groupBox_InternalRes->Controls->Add(this->panel_IntRes); this->groupBox_InternalRes->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->groupBox_InternalRes->ForeColor = System::Drawing::Color::White; - this->groupBox_InternalRes->Location = System::Drawing::Point(8, 186); - this->groupBox_InternalRes->Margin = System::Windows::Forms::Padding(4); + this->groupBox_InternalRes->Location = System::Drawing::Point(5, 124); this->groupBox_InternalRes->Name = L"groupBox_InternalRes"; - this->groupBox_InternalRes->Padding = System::Windows::Forms::Padding(4); - this->groupBox_InternalRes->Size = System::Drawing::Size(395, 124); + this->groupBox_InternalRes->Size = System::Drawing::Size(263, 83); this->groupBox_InternalRes->TabIndex = 20; this->groupBox_InternalRes->TabStop = false; this->groupBox_InternalRes->Text = L"Internal Resolution (Quality)"; - // - // panel_IntRes - // this->panel_IntRes->AutoScroll = true; - this->panel_IntRes->Location = System::Drawing::Point(8, 28); - this->panel_IntRes->Margin = System::Windows::Forms::Padding(4); + this->panel_IntRes->Location = System::Drawing::Point(5, 19); this->panel_IntRes->Name = L"panel_IntRes"; - this->panel_IntRes->Size = System::Drawing::Size(379, 88); + this->panel_IntRes->Size = System::Drawing::Size(253, 59); this->panel_IntRes->TabIndex = 1; - // - // tabPage_Patches - // - this->tabPage_Patches->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), - static_cast(static_cast(64))); + this->tabPage_Patches->BackColor = System::Drawing::Color::White; this->tabPage_Patches->Controls->Add(this->panel_Patches); - this->tabPage_Patches->Location = System::Drawing::Point(4, 29); - this->tabPage_Patches->Margin = System::Windows::Forms::Padding(4); + this->tabPage_Patches->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), + static_cast(static_cast(64))); + this->tabPage_Patches->Location = System::Drawing::Point(4, 22); this->tabPage_Patches->Name = L"tabPage_Patches"; - this->tabPage_Patches->Size = System::Drawing::Size(769, 456); + this->tabPage_Patches->Size = System::Drawing::Size(552, 358); this->tabPage_Patches->TabIndex = 1; this->tabPage_Patches->Text = L"Options"; - // - // panel_Patches - // this->panel_Patches->AutoScroll = true; this->panel_Patches->Location = System::Drawing::Point(0, 0); - this->panel_Patches->Margin = System::Windows::Forms::Padding(4); this->panel_Patches->Name = L"panel_Patches"; - this->panel_Patches->Size = System::Drawing::Size(769, 448); + this->panel_Patches->Size = System::Drawing::Size(552, 358); this->panel_Patches->TabIndex = 9; - // - // tabPage_Playerdata - // - this->tabPage_Playerdata->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), - static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Playerdata->BackColor = System::Drawing::Color::White; this->tabPage_Playerdata->Controls->Add(this->panel_Playerdata); - this->tabPage_Playerdata->Location = System::Drawing::Point(4, 29); - this->tabPage_Playerdata->Margin = System::Windows::Forms::Padding(4); + this->tabPage_Playerdata->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), + static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Playerdata->Location = System::Drawing::Point(4, 22); this->tabPage_Playerdata->Name = L"tabPage_Playerdata"; - this->tabPage_Playerdata->Size = System::Drawing::Size(769, 456); + this->tabPage_Playerdata->Size = System::Drawing::Size(552, 358); this->tabPage_Playerdata->TabIndex = 3; this->tabPage_Playerdata->Text = L"Player"; - // - // panel_Playerdata - // this->panel_Playerdata->AutoScroll = true; this->panel_Playerdata->Location = System::Drawing::Point(0, 0); - this->panel_Playerdata->Margin = System::Windows::Forms::Padding(4); this->panel_Playerdata->Name = L"panel_Playerdata"; - this->panel_Playerdata->Size = System::Drawing::Size(769, 448); + this->panel_Playerdata->Size = System::Drawing::Size(552, 358); this->panel_Playerdata->TabIndex = 1; - // - // tabPage_Components - // - this->tabPage_Components->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), - static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Components->BackColor = System::Drawing::Color::White; this->tabPage_Components->Controls->Add(this->panel_Components); - this->tabPage_Components->Location = System::Drawing::Point(4, 29); - this->tabPage_Components->Margin = System::Windows::Forms::Padding(4); + this->tabPage_Components->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), + static_cast(static_cast(64)), static_cast(static_cast(64))); + this->tabPage_Components->Location = System::Drawing::Point(4, 22); this->tabPage_Components->Name = L"tabPage_Components"; - this->tabPage_Components->Padding = System::Windows::Forms::Padding(4); - this->tabPage_Components->Size = System::Drawing::Size(769, 456); + this->tabPage_Components->Padding = System::Windows::Forms::Padding(3); + this->tabPage_Components->Size = System::Drawing::Size(552, 358); this->tabPage_Components->TabIndex = 2; this->tabPage_Components->Text = L"Components"; - // - // panel_Components - // this->panel_Components->AutoScroll = true; this->panel_Components->Location = System::Drawing::Point(0, 0); - this->panel_Components->Margin = System::Windows::Forms::Padding(4); this->panel_Components->Name = L"panel_Components"; - this->panel_Components->Size = System::Drawing::Size(769, 448); + this->panel_Components->Size = System::Drawing::Size(552, 358); this->panel_Components->TabIndex = 0; - // - // tabPage_Plugins - // - this->tabPage_Plugins->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), - static_cast(static_cast(64))); + this->tabPage_Plugins->BackColor = System::Drawing::Color::White; this->tabPage_Plugins->Controls->Add(this->panel_Custom); this->tabPage_Plugins->Controls->Add(this->panel_Plugins); - this->tabPage_Plugins->Location = System::Drawing::Point(4, 29); - this->tabPage_Plugins->Margin = System::Windows::Forms::Padding(4); + this->tabPage_Plugins->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), + static_cast(static_cast(64))); + this->tabPage_Plugins->Location = System::Drawing::Point(4, 22); this->tabPage_Plugins->Name = L"tabPage_Plugins"; - this->tabPage_Plugins->Padding = System::Windows::Forms::Padding(4); - this->tabPage_Plugins->Size = System::Drawing::Size(769, 456); + this->tabPage_Plugins->Padding = System::Windows::Forms::Padding(3); + this->tabPage_Plugins->Size = System::Drawing::Size(552, 358); this->tabPage_Plugins->TabIndex = 3; this->tabPage_Plugins->Text = L"Plugins and Patches"; - // - // panel_Custom - // this->panel_Custom->AutoScroll = true; - this->panel_Custom->Location = System::Drawing::Point(385, 0); - this->panel_Custom->Margin = System::Windows::Forms::Padding(4); + this->panel_Custom->Location = System::Drawing::Point(276, 0); this->panel_Custom->Name = L"panel_Custom"; - this->panel_Custom->Size = System::Drawing::Size(384, 448); + this->panel_Custom->Size = System::Drawing::Size(276, 358); this->panel_Custom->TabIndex = 3; - // - // panel_Plugins - // this->panel_Plugins->AutoScroll = true; this->panel_Plugins->Location = System::Drawing::Point(0, 0); - this->panel_Plugins->Margin = System::Windows::Forms::Padding(4); this->panel_Plugins->Name = L"panel_Plugins"; - this->panel_Plugins->Size = System::Drawing::Size(384, 444); + this->panel_Plugins->Size = System::Drawing::Size(276, 358); this->panel_Plugins->TabIndex = 0; - // - // tabPage_Credits - // this->tabPage_Credits->Controls->Add(this->creditsTextBox); - this->tabPage_Credits->Location = System::Drawing::Point(4, 29); + this->tabPage_Credits->Location = System::Drawing::Point(4, 22); + this->tabPage_Credits->Margin = System::Windows::Forms::Padding(2); this->tabPage_Credits->Name = L"tabPage_Credits"; - this->tabPage_Credits->Padding = System::Windows::Forms::Padding(3); - this->tabPage_Credits->Size = System::Drawing::Size(769, 456); + this->tabPage_Credits->Padding = System::Windows::Forms::Padding(2); + this->tabPage_Credits->Size = System::Drawing::Size(552, 358); this->tabPage_Credits->TabIndex = 5; this->tabPage_Credits->Text = L"Credits"; this->tabPage_Credits->UseVisualStyleBackColor = true; - // - // creditsTextBox - // - this->creditsTextBox->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), + this->creditsTextBox->BackColor = System::Drawing::Color::White; + this->creditsTextBox->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), static_cast(static_cast(64))); - this->creditsTextBox->ForeColor = System::Drawing::Color::White; this->creditsTextBox->Location = System::Drawing::Point(0, 0); + this->creditsTextBox->Margin = System::Windows::Forms::Padding(2); this->creditsTextBox->Multiline = true; this->creditsTextBox->Name = L"creditsTextBox"; this->creditsTextBox->ReadOnly = true; this->creditsTextBox->ScrollBars = System::Windows::Forms::ScrollBars::Both; - this->creditsTextBox->Size = System::Drawing::Size(769, 456); + this->creditsTextBox->Size = System::Drawing::Size(552, 358); this->creditsTextBox->TabIndex = 0; this->creditsTextBox->Text = resources->GetString(L"creditsTextBox.Text"); - // - // button_Discord - // - this->button_Discord->BackColor = System::Drawing::Color::Transparent; + this->button_Discord->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(242)), static_cast(static_cast(242)), + static_cast(static_cast(242))); + this->button_Discord->Cursor = System::Windows::Forms::Cursors::Hand; this->button_Discord->FlatAppearance->BorderSize = 0; - this->button_Discord->FlatAppearance->MouseDownBackColor = System::Drawing::Color::Transparent; - this->button_Discord->FlatAppearance->MouseOverBackColor = System::Drawing::Color::Transparent; this->button_Discord->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_Discord->Image = (cli::safe_cast(resources->GetObject(L"button_Discord.Image"))); - this->button_Discord->Location = System::Drawing::Point(674, 489); - this->button_Discord->Margin = System::Windows::Forms::Padding(4); + this->button_Discord->Location = System::Drawing::Point(496, 384); this->button_Discord->Name = L"button_Discord"; - this->button_Discord->Size = System::Drawing::Size(48, 48); + this->button_Discord->Size = System::Drawing::Size(32, 32); this->button_Discord->TabIndex = 31; this->button_Discord->UseVisualStyleBackColor = false; this->button_Discord->Click += gcnew System::EventHandler(this, &ui::button_Discord_Click); - // - // button_github - // - this->button_github->BackColor = System::Drawing::Color::Transparent; + this->button_github->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(242)), static_cast(static_cast(242)), + static_cast(static_cast(242))); this->button_github->Cursor = System::Windows::Forms::Cursors::Hand; this->button_github->FlatAppearance->BorderSize = 0; - this->button_github->FlatAppearance->MouseDownBackColor = System::Drawing::Color::Transparent; - this->button_github->FlatAppearance->MouseOverBackColor = System::Drawing::Color::Transparent; this->button_github->FlatStyle = System::Windows::Forms::FlatStyle::Flat; this->button_github->Image = (cli::safe_cast(resources->GetObject(L"button_github.Image"))); - this->button_github->Location = System::Drawing::Point(729, 489); - this->button_github->Margin = System::Windows::Forms::Padding(4); + this->button_github->Location = System::Drawing::Point(528, 384); this->button_github->Name = L"button_github"; - this->button_github->Size = System::Drawing::Size(48, 48); + this->button_github->Size = System::Drawing::Size(32, 32); this->button_github->TabIndex = 32; this->button_github->UseVisualStyleBackColor = false; 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->FlatAppearance->BorderColor = System::Drawing::SystemColors::Control; this->button_Apply->FlatStyle = System::Windows::Forms::FlatStyle::Flat; - this->button_Apply->Location = System::Drawing::Point(225, 496); - this->button_Apply->Margin = System::Windows::Forms::Padding(4); + this->button_Apply->Location = System::Drawing::Point(4, 389); this->button_Apply->Name = L"button_Apply"; - this->button_Apply->Size = System::Drawing::Size(104, 34); + this->button_Apply->Size = System::Drawing::Size(69, 23); this->button_Apply->TabIndex = 33; this->button_Apply->Text = L"Apply"; + this->button_Apply->UseVisualStyleBackColor = false; this->button_Apply->Click += gcnew System::EventHandler(this, &ui::button_Apply_Click); - // - // ui - // + this->button_Wiki->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(242)), static_cast(static_cast(242)), + static_cast(static_cast(242))); + this->button_Wiki->BackgroundImage = (cli::safe_cast(resources->GetObject(L"button_Wiki.BackgroundImage"))); + this->button_Wiki->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch; + this->button_Wiki->Cursor = System::Windows::Forms::Cursors::Hand; + this->button_Wiki->FlatAppearance->BorderSize = 0; + this->button_Wiki->FlatStyle = System::Windows::Forms::FlatStyle::Flat; + this->button_Wiki->Location = System::Drawing::Point(464, 384); + this->button_Wiki->Name = L"button_Wiki"; + this->button_Wiki->Size = System::Drawing::Size(32, 32); + this->button_Wiki->TabIndex = 34; + this->button_Wiki->UseVisualStyleBackColor = false; + this->button_Wiki->Click += gcnew System::EventHandler(this, &ui::button_Wiki_Click); this->AcceptButton = this->button_Launch; - this->AutoScaleDimensions = System::Drawing::SizeF(144, 144); + this->AutoScaleDimensions = System::Drawing::SizeF(96, 96); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Dpi; this->AutoSize = true; this->AutoSizeMode = System::Windows::Forms::AutoSizeMode::GrowAndShrink; - this->BackColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), - static_cast(static_cast(64))); + this->BackColor = System::Drawing::Color::Magenta; this->BackgroundImageLayout = System::Windows::Forms::ImageLayout::Stretch; - this->ClientSize = System::Drawing::Size(778, 538); + this->ClientSize = System::Drawing::Size(560, 417); + this->Controls->Add(this->button_Wiki); this->Controls->Add(this->button_Apply); this->Controls->Add(this->tabControl); - this->Controls->Add(this->button_Help); this->Controls->Add(this->button_Launch); this->Controls->Add(this->button_github); this->Controls->Add(this->button_Discord); this->DoubleBuffered = true; - this->ForeColor = System::Drawing::Color::White; - this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog; + this->ForeColor = System::Drawing::Color::FromArgb(static_cast(static_cast(64)), static_cast(static_cast(64)), + static_cast(static_cast(64))); + this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D; + this->HelpButton = true; this->Icon = (cli::safe_cast(resources->GetObject(L"$this.Icon"))); this->KeyPreview = true; - this->Margin = System::Windows::Forms::Padding(4); this->MaximizeBox = false; - this->MinimizeBox = false; this->Name = L"ui"; this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen; this->Text = L"PD Launcher"; + this->TransparencyKey = System::Drawing::Color::Magenta; this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &ui::Ui_FormClosing); this->FormClosed += gcnew System::Windows::Forms::FormClosedEventHandler(this, &ui::Ui_FormClosed); - this->Load += gcnew System::EventHandler(this, &ui::Ui_Load); this->groupBox_ScreenRes->ResumeLayout(false); this->tabControl->ResumeLayout(false); this->tabPage_Resolution->ResumeLayout(false); this->tabPage_Resolution->PerformLayout(); + this->groupBox_Lag->ResumeLayout(false); + this->groupBox_Lag->PerformLayout(); + (cli::safe_cast(this->trackBar_LagCompensation))->EndInit(); this->groupBox_Details->ResumeLayout(false); this->groupBox_InternalRes->ResumeLayout(false); this->tabPage_Patches->ResumeLayout(false); @@ -814,6 +858,12 @@ private: System::Void SaveSettings() { *ComponentsConfigChanged = false; } + if (*LagCompensationConfigChanged) + { + SetIniInt(GRAPHICS_SECTION, L"lag_compensation", trackBar_LagCompensation->Value, CONFIG_FILE); + *LagCompensationConfigChanged = false; + } + for (ConfigOptionBase* option : AllPluginOpts) { if (*(option->hasChanged)) @@ -834,8 +884,6 @@ private: System::Void SaveSettings() { *(option->hasChanged) = false; } } -private: System::Void Ui_Load(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"); } @@ -931,13 +979,25 @@ private: System::Void Ui_FormClosed(System::Object^ sender, System::Windows::For TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS); } private: System::Void button_Discord_Click(System::Object^ sender, System::EventArgs^ e) { - System::Diagnostics::Process::Start("https://discord.gg/cvBVGDZ"); + 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: + System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader"); + break; + + case System::Windows::Forms::DialogResult::No: + System::Diagnostics::Process::Start("https://discord.gg/cvBVGDZ"); + break; + } } private: System::Void button_github_Click(System::Object^ sender, System::EventArgs^ e) { System::Diagnostics::Process::Start("https://notabug.org/PDModdingCommunity/PD-Loader"); } private: System::Void button_Apply_Click(System::Object^ sender, System::EventArgs^ e) { SaveSettings(); + updateStyle(); + ShowWindow(hWnd, SW_HIDE); + ShowWindow(hWnd, SW_SHOW); } private: System::Void Ui_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e) { if (e->KeyCode == Keys::Escape) this->Close(); @@ -947,9 +1007,10 @@ private: bool* ResolutionConfigChanged = new bool(false); bool* OptionsConfigChanged = new bool(false); bool* PlayerdataConfigChanged = new bool(false); bool* ComponentsConfigChanged = new bool(false); + bool* LagCompensationConfigChanged = new bool(false); private: bool AnyConfigChanged() { - if (*ResolutionConfigChanged || *OptionsConfigChanged || *PlayerdataConfigChanged || *ComponentsConfigChanged) + if (*ResolutionConfigChanged || *OptionsConfigChanged || *PlayerdataConfigChanged || *ComponentsConfigChanged || *LagCompensationConfigChanged) return true; // fast case for (ConfigOptionBase* option : AllPluginOpts) @@ -964,5 +1025,17 @@ private: String^ GPUIssueText; private: System::Void LinkLabelLinkClickedGPUIssueHandler(System::Object^ sender, System::Windows::Forms::LinkLabelLinkClickedEventArgs^ e) { SkinnedMessageBox::Show(this, GPUIssueText, "PD Launcher", MessageBoxButtons::OK, MessageBoxIcon::Warning); } +private: System::Void trackBar_LagCompensation_ValueChanged(System::Object^ sender, System::EventArgs^ e) { + *LagCompensationConfigChanged = true; + + updateLagCompMsec(); +} +private: System::Void tabPage_Resolution_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"); +} +private: System::Void trackBar_LagCompensation_Scroll(System::Object^ sender, System::EventArgs^ e) { +} }; } diff --git a/source-code/source/plugins/Launcher/ui.resx b/source-code/source/plugins/Launcher/ui.resx index 22f0ed0..d010943 100644 --- a/source-code/source/plugins/Launcher/ui.resx +++ b/source-code/source/plugins/Launcher/ui.resx @@ -294,8 +294,221 @@ AMD compatibilty pack dependencies have additional licenses, detailed in the AMD ZSNnuf0xq38QLKYcn/7WyZSb81ROzr/0gUC6FNUQmwAAAABJRU5ErkJggg== - + 17, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAAikAAAIrCAYAAAAqWwkVAAABgmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkUso + RFEcxn/uEIksjDyyuAusKCFZaogUpTHKa+HeO2aouXeme0c2lspWWXhsDBY21mwtbJVSHiU7OytiI13/ + c0fNpEY5dTq/vnO+r3O+A1ouZdleeTfYTtaNjkb0mdk5vfIZjWYaaKTRsLzMxNRIjJLj45Yytd50qSz+ + N2rjS54FZbrwoJVxs8KLwv1r2YziXeGwtWzEhU+FO125oPC90s08vyhOBqypzLAbiw4Jh4X1ZBGbRWwt + u7Zwn3Bb3HYkX5vJc1zxumI7tWr93FO9sGbJmZ5SusxWRhljgkl0TFZZIUWWLlkdUTyish8p4W8J/JPi + MsW1giWOYdLYGIEf9Qe/u/USvT35pJoIVDz5/ls7VG7D15bvfx76/tcRhB7hwin40zkYeBd9q6C1HUDd + BpxdFjRzB843oekhY7hGIIVkaokEvJ7IN81C/TVUz+d7+9nn+A5i0tX4FeztQ0dSshdKvLuquLc/zwT9 + EfkGd8VyqcjB1fkAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQflAhkVFx2h5OIwAAAu70lEQVR4 + Xu3d/8+9913QcRL/gf7gD8aI/qA/aGJi/EGIJuoPhphFgtGEkZiYqCHGBONPg0iMUjUkxs0VRGAIhQ4D + 6CKBNNgIlBXY1q3r2rVl30q2ABW6sTG20vXTzzq22/M67WnPfe7Xfd/XOed9Xdf7y+OVPK7t824/n8/5 + fj17Xec+5+suLi4AZnP3hTv3hP/3/k/97UOxnv0egJAuApwqwuORex+8L/yXr//Oi6ni3xcuwL50EeAY + uzDJ4uMUu2DJ/i5gHOkiwBSl4yQjVmBc6SLATZaIk0NiBcaTLgJcJ2Ihi4gleM8KjCVdBMisGSj7HFWB + MaSLAIeWPr0zhViBvqWLAPtqDJQdPwkE/UoXAXZqDpR9QgX6ky4ChFYCZZ9YgX6kiwCxs88ioAVOAUEf + 0kVgbC0Hyj6hAm1LF4Fx9RIo+8QKtCldBMbUY6DsEyvQlnQRGE/vgbIjVKAd6SIwllECZZ9Ygfqli8A4 + RgyUfWIF6pUuAmMYPVB2hArUKV0E+idQrhIrUJd0EeibQLmZWIE6pItAvwTKNEIF1pcuAn0SKMcTK7Ce + dBHoz90X7tyT7YSZRqzA8tJFoC8CpQyhAstKF4F+CJTyxAosI10E+iBQ5iVWYF7pItA+gbKMCJW4rbP7 + ADhPugi0L9uhMh9HVaC8dBFo2yP3PnhftiNlfmIFykkXgXYJlPU5BQRlpItAmwRKXRxVgfOki0B7BEq9 + xAqcJl0E2iJQ6hf3kViB46SLQDsESluECkyXLgJtiB1etiOkfmIFbpcuAvUTKO1zCghuli4CdRMofREq + kEsXgXoJlH6JFbgsXQTqJFDGIFbgVekiUB+BMhahAiIFmiBQxiVWGFm6CNRDoBDECiNKF4E6CBT2CRVG + ky4C6xMoXEesMIp0EViXQGEKsULv0kVgPQKFYwgVepYuAuu4+8Kde7IdEdxGrNCjdBFYnkChBLFCT9JF + YFkChZKECr1IF4HlCBTmIlZoXboILEOgsASxQqvSRWAZ2Q4F5hChElGcPQ6hVukiML9H7n3wvmxnAnNy + VIWWpIvAvAQKaxMrtCBdBOYjUKiFU0DULl0E5iFQqJGjKtQqXQTKEyjUTqxQm3QRKCte/LOdAtQmYlqs + UIt0EShHoNAioUIN0kWgDIFC68QKa0oXgfMJFHrhFBBrSReB8wgUeiRUWFq6CJxOoNA7scJS0kXgNAKF + kYgV5pYuAscTKIxIqDCndBE4jkBhdGKFOaSLwHQCBd4gVigpXQSmEShwlVChlHQRuJ1AgZuJFc6VLgI3 + i6+3z16UgavECqdKF4HrCRQ4nlDhFOkikBMocB6xwjHSReAqgQLliBWmSBeBywQKlCdUuE26CFyWvcAC + ZYgVrpMuAm+Ir6nPXliBssQKh9JF4FUCBZYVoRKnV7PnI+NJFwGBAmtyVIWQLsLoBArUQayMLV2EkQkU + qItTQONKF2FU8WKYvUgC63NUZTzpIoxIoEAbxMo40kUYjUCBtsRpWbHSv3QRRiJQoF1CpW/pIoxCoEAf + xEqf0kUYgUCp27ve/I7Jst/PeJwC6k+6CL0TKOvaxcWjb/+li+ce/eTrSszuz4o/O4iY8QiVfqSL0DOB + sqz9GFl79uMlu6z0Ray0L12EXgmU+UWU7I5mtDCipX9ipV3pIvRIoMxjd+qmlSi5aXZHWrLrSduESpvS + ReiNQCmvlzC5bgRLn8RKW9JF6IlAKaf3MLluBEt/xEob0kXoRXwpWfYCxXFGjZNsvIelH0Klfuki9ECg + nE+cXD+OrvRDrNQrXYTWCZTziJPjRqz0QazUJ12ElgmU04mT80astE+o1CVdhFYJlNOIk7IjVtonVuqQ + LkKLBMppYodq5hmx0j6xsq50EVoUXy6WvciQc/RkuRErbRMq60kXoTUC5TiOnqwzYqVtYmV56SK0RKBM + 5+jJ+iNU2idWlpMuQisEynSOntQ1YqVtESrxPrjNXZm+NlFGuggtECjTOXpS74iVtjmqMq90EWonUKaJ + 0zum/hEq7RMr80gXoWbxYpC9SHCZ0zvtjVhpm1NA5aWLUCuBMo1AaXeESvscVSknXYQaCZRpBEofI1ba + J1bOly5CbQTKNN4g29cIlfbF++fEyunSRaiJQJlGoPQ5cb9m9zdtESqnSRehFgJlGoHS/ziq0gexcpx0 + EWogUKYRKOOMUOmDU0DTpYuwNoEyjUAZb4RKP4TK7dJFWJNAmUagjDvep9IXsXK9dBHWIlCmif+aNiY+ + UTh7fNAmsXJVughrECjTCBSzP07/9EWoXJYuwtIEyjQCxWQjVPojVl6VLsKS4rsusicplwkUc9MIlT6N + HivpIixFoExnzG0jVPo0cqiki7AEgTKdn+QxU0eo9GvEWEkXYW4CZTqnecyxI1T6NlKspIswJ4EynUAx + p45Q6dsooZIuwpyyJxw5Y84ZodK/3mMlXYS5xHdWZE80rhr5KEq8ByfEbRAfWLaT3U5h98/j39/xPp5X + J26L7DajL73GSroIcxAo08WOZaSJoLgtRE61Hy+jzhy3K/XpMVTSRShNoBxnhKMAuzDJrv+cdtEy2giV + cfQUK+kilCRQjtfrrBUm1xkpWOK2z24D+tVDrKSLUIpAOV7sOHub2uIkM8IpIaEyngiV+InKzd2fvkbX + Ll2EEuLJkT1puFlPkdJCnBzq/ehKXLfsetO3Vo+qpItwLoFyuh4ipcU4yfQaKz3cN5ymtVhJF+EcAuV8 + LU+P/6XeY6wIlXHFa3Qrp4DSRTiVQCkjjkS0Nr0cPblOhEpPseL9KbRwVCVdhFMIlHJaO+XT49GT6/QU + KiPdb1yv5lhJF+FYAqW8Fo6m9H705Ca9xIrTPoT4ScwaYyVdhGMIlPnUPP4rvI9QcdqHfbWFSroIUwmU + ecV/5dZ4REWgXNZ6rLg/OVRLrKSLMIVAWU5NO0GnB3Kth4r7lUM1nAJKF+E2AmUda+8I7chu18J7ibJx + 2ofrrBkq6SLcRKCsa41QGfkNsqdo9ahKXO7s+kBYI1bSRbiOQKnHUjtC/4V9mlZDRYxymyVjJV2ETHxC + YfaAZV1z7gwFynlih9/auM+ZYqlQSRfhkECp2xyhYmdVRouh4mgKU80dK+ki7BMo7SgZK9mfz+ki+loZ + gcqx5oqVdBF2BEqbzo0V/yU9j5ZCxWOAY80RKukiBIHStlNCJXaidk7zaiVUHE3hVCVjJV2EkD34aM/U + WIl/L/v9lNdKqAhWzlEiVtJFiE8azB50tCsiJMQOcid+bUe0vLjNWxhHUzjXuaGSLjI2gQLzayVURCwl + nBor6SLjEiiwnKmn4tYcR1Mo6dhYSRcZk0CB5bUQKo6mUNIxoZIuMh6BAuuJoxU1j6MplDY1VNJFxhIP + luxBBCyn9skuM5wj/uN489BK90s76SLjEChQh9rfSOuUD3O4LVTSRcYgUKAuNZ/2ccqHudx06iddpH8C + BepU8ziawlyuC5UrC/RPoEC9aj7tI1KYU3wVy+Zhdml/dekX9E+gQP1qPe3jlA9zyt6fcukX9E2gQBsc + TWFUh6d9Lu3E6JdAgbbUejRFpDC3zby+77q0I6NPAgXaU+vRFKd8mNv+0ZQrOzT6IlCgXbUeTckuK5Sy + /96UKzs1+iFQoG21Hk1xyoe57X7SJ9250T6BAn2o8WiKUz7MbXc0Jd3B0bYo0OxOB9pT49EUkcISNiNS + eiNQoD81Hk3JLieUFPuzdEdHmwQK9KnGoynel8LcREpHBAr0S6QwonhfSrrDoy0CBfpX2ykf70thbiKl + AwIFxlDb0RSRwtxESgfiTszuXKAvNZ7yyS4nlJTu+GiDQIGx1DbZZYSS0p0f9RMoMJ7a3pfizbPMLd0B + UjeBAmN69O2/tHkJqGdECnPynpQGCRQYV23vS4loyi4nlCBSGiNQYGwihZHEd9ClO0Pq4wsDAZHCSERK + IwQKsFPT+KwU5uRj8RsgUIB9NY1IYU6b8S3INRMowKGaRqQwl3gP5uYhJlJqJVCATE0jUphL7AM3DzGR + UiOBAlynphEpzGUz2/3hlR0k6xIowE1qGpHCHHZHUcKVnSTrESjAbWoakcIcNvP6fvHSTpL1CBTgNrV9 + TopIobT9oyjh0o6SdQgUYIravrtHpFDaZi7tHy/9guUJFGAqkULPDo+ihEu/YFkCBThGREFN42PxKSUL + lHBlgWXEx/1mdxTAdWobkUIpm0n3leki8xIowLFqe9NsjEihhNgnbh5O6f4yXWQ+AgU4RW3vR4kRKZzr + pkAJ6SLzECjAqWqcOLqTXVaY4rr3oexLFylPoACnqvFUT0x2WWGKX3nbg+/ZPITS/eW+dJHysjsJYIoa + T/XEZJcVbvO/3/LAxXPPPbf9luPbpIuUFV85nd1RAFPUOD4jhVNEoHzoQx8SKbUQKMA5aj2K4k2zHGsX + KCKlEgIFOFetI1I4xn6giJQKCBTgXLUeRYnxkz1MdRgoImVlAgUooebJLi8cygJFpKzI9/EAJdR8FMWb + ZpniukAJImUFAgUopebxfhRuc1OgBJGyMIEClFLzUZQY70fhJrcFShApCxIoQCm1B0pMdrkhTAmUIFIW + IlCAkmofp3q4zv1vemsaJBmRsgCBApQUb0itfUQKmWMCJYiUmQkUoKQWTvPEZJedsR0bKEGkzEigACW1 + EiiOonDolEAJImUmAgUoKX5SppURKew7NVCCSJmBQAFKailQYrLrwJjOCZQgUgoTKEBJrQWKoyjsy8Lj + GCKlIIEClNRaoMRk14MxPfzAQ2l4HEOkFHL3hTv3ZHcSwClaDBRHUdgpEShBpBQgUICSWvkpnsPJrgvj + KRUoQaScSaAAJbUaKI6iEEoGShApZxAoQClxeqeFT5K9brLrxFhKB0oQKScSKEAprR492Y2jKEz9wsBj + iZQTZXcSwDFafHNsNtl1YxxzBUoQKSd45N4H78vuKIApWj+1sz+OooxtzkAJIuVIAgU4RYRJ66d1ssmu + K2OYO1CCSDmCQAGO1dNRk8NxFGVcSwRKECkTCRRgql2Y9BonMXHdsutO/5YKlCBSJhAowG1GCJP9cRRl + TEsGShApt/B9PMB1RguT3QiUMS0dKEGk3ECgAPsiSnp+j8nUyW4b+rZGoASRcg2BAoRRj5ZcN46ijGet + QAkiJSFQYEz7R0pEydURKONZM1CCSDkgUGAcomT6xO2T3Yb0a+1ACSJlj0CBfgmS8yZuu+x2pU/3v+mt + aTQsTaS8RqBAXwRJuXGaZyy1BEoQKRsCBdrmKMl8I1DGUlOghOEjRaBAe/ajxMw3AmUstQVKGDpSBAq0 + QZQsP3FbZ/cFfaoxUMKwkSJQoG5O36w3AmU8WSDUYMhIEShQn4iSOL0gStafuC+y+4g+PfzAQ2kg1GC4 + SLn7wp17sjsJWJ5TOPWNQBlLzYEShooUgQLrEyb1jkAZS+2BEoaJFIEC6xEmdU/cNwJlLC0EShgiUgQK + rEOc1D9x/2T3Hf1qJVBC95EiUGB58QZYU//4HJTxtBQooetIESiwLHHSzgiU8dTwhYHH+sAvvOe3Y1++ + ecim+/mddLF22Z0ElCdO2hrvPxlPi4ES4shPXP7bQiVdrNkj9z543+GdBJTlPSdtjfefjKnVQAm7SAmb + Sff3IV2slUCBeYmT9sbpnTG1HChhP1Ji3755KKf7/XSxRgIF5uXUTlsTMen0zphaD5SwHykhPjF+87C+ + su+/slAjgQLzcfSkvREn4+ohUMJhpITs/SmXflEjgQLzcfSkrXFqZ2y9BErIIiVs5lIDXPpFbXxhIMzD + 0ZO2xqkdegqUcF2kHJ72uRQFNREoMA9HT9oZcULoLVDCdZES9k/7XImDGggUmIdAaWPECTs9Bkq4KVL2 + f9rnSiCsTaDAPJzeqX/ECft6DZRwU6SEzWyb4EokrEmgwDwESt0jTjjUc6CE2yJld8onjYU1CBSYh0Cp + c4QJ17n/TW9Nd+w9uS1Sdqd80mBYmkCB8mIHKFDqGmHCbUYIlPCz3/nO9Prv28z6kSJQYB4CZf2J+0CY + MNUogRLiuma3wb445ZOGw1IECsxDoKwz+1EiTDjGSIEy5ShKiEZI42EJAgXmIVCWG1FCCQIlF+9LSQNi + bgIF5uFzUOYdUcIcsp15j44JlLBKpAgUmIdAKTuChCXET7lkO/TeHBsoYfFIiTfBZBcEOI9AOW8ECWsQ + KLdLY2IOAgXmY6aPIKEGAmWaNChKEygwn9jhmusnbp840iRIqIVAmS6NipIECszHaZ6r4ygJNRMo083+ + nhSBAvMRKK+OKKEVvX8fz06JQAmzR0r2lwJljDoRJbswyW4XqNEogRJHirLrf4pZP8wtCij7S4HzjXYU + RZjQMoFymtkiRaDAfEYJFGFCDwTK6eItI2lknEOgwLxix93zCBN6IVDOs5my34IsUGBevR5FESb0RqCc + J071bF4aykWKQIH59TbihB6NEighvhwxuw3OVTRSfB8PzK+noyjihF4JlDI2s+2LK8FxLIECy+hhxAk9 + Eyhl7I6ihCvRcQyBAsto/SiKOKF3AqWczbzeGZei4xgCBZbReqDE5c+uF/RCoJSzfxQlXAqPqQQKLKfl + SHH0hN6NFCilPu7+Jpu51BuXfjGFQIHltBoocXonuz7QkziqkO3Me7REoBweRQmXfnEbgQLLanGc3mEE + AqWsLFDClYXrCBRYVotHUQQKIxAoZcXnrG1ePtL2SBcPCRRYXmsjUBiBQCnrpkAJ6eI+gQLLa+0oikBh + BAKlrNsCJaSLOwIF1hFvPG1lBAojECjlxbccb15C0v7YSRdD/ObsDwXm18oIFEYRX6SX7dB7U1OghHQx + ZH8osIxWJrvs0BuBUtbUQAnpotM8sK4Wxge1MYJRAiWuZ3b9SzsmUMKVBYEC66t9nOZhBAKlrGMDJVxZ + yP5gYFk1v3FWoDACgVLWKYESLv3CURSoQ82Rkl1e6IlAKSvaYvPScak3prr0i+wPB5YX7/eocRxFoXcj + fWFgdv1LOydQwuv/x1EUqEttR1MECr0bKVDic1+y26CkcwMlvP5/4pPfsr8EWEdtR1Oyywi9EChllQiU + 8Pr/2f/D37b937e8/uvL3vLaPwfmFkcvahhHUeiZQCmrVKCE7capHqhXDaGSXS7ogUApq2SghO1GpEDd + 1gwVR1Ho1UiBssSnyZYOlLDdZH8ZUJ+lY0Wg0CuBUtYcgRK2m+wvBOoU4bDUT/746Ht6JFDKmitQgm87 + hkbNfVTFURR6JFDKmjNQwquR8mfyv3yyc38/cLK5YiX7u6BlAqWsuQMlOJICHSh9CshRFHojUMpaIlCC + SIGOlDiqIlDojUApKz78dfNSkUZFaSIFOnRqrAgUehOfDZLtzHvUW6AEkQKdiuCYGitxqshP8tAbgVLW + 0oESRAp07qZYESf0SqCUtUaghO0mu0AA0KKRAuXhBx5Kb4OS1gqUsN1kFwoAWiNQytuPhqVtNz/yDd/7 + XHbBAKAl2c68R0sFSrwl5DAclrTd/Py3v/PnsgsHAK2IHXe2Q+/NKIESthuRAkDLRgmUkF3/0moIlLDd + /PJ3/+wPZxcSAGo3UqDEe26y26CkWgIlbDciBYAWCZSyagqUsN2IFABaI1DKWur7eI6x3YgUAFoy0vfx + jBooYbsRKXCe+NTW+PTW7JuId5/4mv0+4Hi+MLCsWgMlbDciBU6zi5MpE6HiI+jhPAKlrJoDJWw3IgWO + d9334dw2jqrAaQRKWbUHSthuRAoc59RA2R+xAtMJlLJaCJSw3YgUmK5EoOwmThWJFbiZQCmrlUAJ241I + genmGKECOYFSVkuBErYbkQLTlDyKko1YgTcIlLJaC5Sw3YgUmGaJcQoIBEppLQZK2G5ECtxu7qMohyNU + GJVAKavVQAnbjUiBmy0dKPsjVhiJQCmr5UAJ241IgZutGSm7ESv0bqRAie8dym6Dkh6598H7Ni8dV3b8 + LdluRApcr4ZA2Y1QoVfx/TTZzrxHAmW67UakwPVqHLFCTwRKWb0ESthuzo2Un/kHP+hFky7VdBQlG887 + WidQyuopUMJ2UyJSduNFk560MJ5ztGqkQAnZbVBSb4EStpuSkRLjRZMe1H4UZX8852jNaIES1ze7HUrp + MVDCdlM6UnbjhZOWtTbvevM70usBtREo5W3myg6+B9vNXJGyG7FCa1o6irKb+KTa7LpAbbIdea+WCJS7 + L9y5Z/MScGUH34PtZu5IiREqtKLFQNmNoynULt48mu3MeyRQzrfdLBEpuxEr1K7lSHE0hZqNFChLfJps + 74EStpslI2U3YoUatRwoMSKFWgmUskYIlLDdrBEpMUKF2vQw2fWCNQmUskYJlLDdrBUpuxEr1KD1oyi7 + ya4brEWglNX6FwYea7tZO1J2I1ZYUy+TXTdYg280Lmu0QAnbTS2REhOh4icUWFovR1FisusHSxMoZY0Y + KGG7qSlSduOoCkvqZbxxlhoIlLJGDZSw3dQYKbsRK8ytp6Moni+sTaCUNXKghO2m5kiJiRdep4CYS0+T + XT9YikApa/RACdtN7ZGyG/+VSGmOokAZIwVK/MRSdhuUJFBetd20Eim78WJMKT1FSnb9YAkCpSyB8obt + prVIiYk3CIoVzhWPox7Gc4G1CJSyBMpl202LkbIbL86co5dIya4bzE2glCVQrtpuWo6U3YgVTtFDpHjs + swaBUpZAyW03PURKjFNAHKv1SInLn10vmNNIgRLuf9Nb09uhFIFyve2ml0jZjVBhqvjR9pbHY52lCZSy + Hrn3wfs2T+UrO2detd30Fim78QLObVqOFI9vlhY77GxH3iuBsr7tptdI2Y0Xc27S6imf7LrAXARKWQJl + mu2m90iJESpcp8WjKR7PLEmglCVQpttuRoiU3XhxJxOPi5Ymuw4wh9ECZe6Puxcox9luRoqU3YgVDrUS + Kh67LEWglLeZKztirrfdjBgpMV7sOdRCqGSXG+aQ7ch7tUSg3H3hzj2bp/CVHTHX225GjZTdiBX2xXtU + ao0Vj1WWEh9glu3MeyRQ6rXdjB4pu7EDYF9toeLxyVIESlkC5XTbjUh5Y+wIOFRLrHhssgSBUpZAOc92 + I1Kujh0C+9Y+BeTxyBIESlkC5XzbjUi5fuwc2LdWqGSXBUoSKGUJlDK2G5Fy8wgVDi0ZKx5/zE2glOUL + A8vZbkTKtLGz4NASsZL9vVDKSF8YGDGW3QYlCZSythuRctyIFfbNGSoea8xJoJQlUMrbbkTK8RM7j3gz + ZXZ7MKbSsRJffJj9PVCCQClLoMxjuxEpp4//0uVQqVgRwcxFoJQlUOaz3YiU80essO/cUBEozGWkQAnZ + bVCSQJnXdiNSykzsmOxc2HdsrMQpHo8h5jJaoMQXJGa3QykCZX7bjUgpO46qcOi2WBEnzE2glCVQlrHd + iJR5RqxwKEIkHhc78WtxwtwESlkCZTnbjUiZb+K/kMUKsBaBUpZAWdZ2I1LmH6ECLG20QJn702QFyvK2 + G5Gy3IgVYAkCpSyBso7tRqQsO04BAXMSKGU9cu+D921euq/sQJnfdiNS1hmhApQW78nIduS9Eih9225E + yrojVoASBEpZAmV9241IWX+cAgLOIVDKEih12G5ESj0jVIBjCZSyBEo9thuRUt+IFWAKgVLeZq7sLFnH + diNS6h2xAtwk25H3aolAufvCnXs2L71XdpasY7sRKXWPUAEyDz/wULoz75FAGdN2I1LaGLEC7IwUKHFd + s9ugJIFSp+3m57/9nT+X3WlTiZRlR6zA2ARKWQKlXtvNT3/LD7w/u+OmEinLj1CBMQmUsgRK3babH/mG + 730uu/OmEinrjViBcQiUsnwfT/22m+zOO4ZIWX/ECvRttO/jyW6DkgRKG7ab7A48xtKR8txzz1189rOf + fe1XZjdCBfo0WqDEZ79kt0MpAqUdXxfn47I78RhLRspv/dZvXTz11FPbB/KHP/zhi8997nOv/ROzG7EC + /RAoZQmUtjQVKb/zO7/zeqDsxK+ffvrpiz/4gz947d8yuxEr0DaBUpZAaU8zkRKneOLISfbAfuKJJy5+ + 4zd+Yxsrf/iHf/ja7zAxQgXaJFDKEihtaiJSfvd3f/faQDn0zDPPbH3hC1947XebGLEC7RgtUOb+NFmB + 0q7qI+X3fu/3rpzimSJCJY6ufPGLX3ztTzIxYgXqJlDKEihtqzpSnn/++clHUK4Tp4B+8zd/8+KP/uiP + XvtTTYTKu978jvS+BNYjUMoSKO0rEikhdnwl59Of/vTZgbLz+OOPb4/GfPKTn7x48cUXX/sbjKMqUA+B + UpZA6cN2k93BpygVKr//+79/8eSTT6YP7HNF+HzqU5+6eOmll17724xYgXUJlLIESj+2m3M/Fv/QObES + H9J2yntQjhFHViKC4jNX7ty589rfPPbEfeYUECxPoJQlUPqy3fz3bywbKTvHxkp8MFvEQ/xIcfbgnkP8 + ffH5Ky+//PJrl2LscVQFliNQynrk3gfv27yMXdnR0a7t5lf/w4Nvz+7wEqaGSnwYW6n3oJwqPovly1/+ + 8muXaOwRKzCv+FyQ7HWoVwKFU2w3z/7C09+a3ekl3RQrn//852d7D8ox4jRQ/G98Lssrr7zy2qUbd557 + 9JNiBWYgUMoSKP3abr721a/9ieyOLy0LlfjQtSVP79xmFyohPqPlK1/5ymuXdNwRKlCOQClLoPTt9f/z + 5E+8719mD4Bb/dnvytdvsIuV+KC17EFdkzjCE5/X8rWvfW17mUcesQLnGS1QHn7gofR2KEWg9O/SL96W + PAhucuy/v+/H/97btg/i/SMXNYtY+cxnPrO5mcYep4DgNAKlLIEyhku/+O1fe/absgdDaT/2d//zxeOP + tREnh+InkIyjKnAMgVJefBDp5qXo0j6M/lxZiDv/bV//lvRBsXPbP7/Jj/6d/3TxwUcfq+p9KFN97GMf + 29xEZn/ECtwudtrZa0qPBAolXVko9TH5mXf8re+9eOy9H0gf2DWLU1IC5eYRK5AbKVBCdhuUJFDGki7G + ub7swXGOH/7r//HiA7/+/vRBXbsIlK9+9aubm8bcNEIFLhstUOK0VnY7lCJQxpMuhuwBcqof+mv//uL9 + v/po+qCu3Uc/+tGLP/7jP97cJGbqiBUQKKUJlDGli6HUaZ//9le/5+L9735f+qCu3Uc+8hGBcsaIFUYl + UMoSKONKF3fii5qyB8xUP/CX/+3Fo7/83vRBXbtnnnnGB7kVGKHCaARKWb4wcGzp4r5TQ+X7/+K/uXjf + L/56+qCu3dNPP+1j8QuPWGEEvjCwLIFCunjo2FD5vr/w3RfvfejX0gd17SJQfMngfCNW6JVAKUugENLF + zOT3qPy577p47/9pL1Dic1sEyjIjVOiNQClLoLCTLt7ktqMq7/6pX0wf1LX78Ic/fHH37t3NVTRLjVih + BwKlLIHCvnTxNteFyq/85P9NH9S1i0B5+eWXN1fNrDFihVYJlLIECofSxan2Y+Xhn2jzHe3xxYF37tzZ + XB2z5ggVWiNQyhIoZNLFYz31niffnT2oaxYfdR9HUARKXSNWaIFAKUugcJ108RjPP//8v8se1LWLIygv + vfTS5iqYGkesUCuBUpZA4Sbp4lSf/vSn/3X2oK5d/CTPiy++uLkKpuaJUHnXm9+RvrDBGgRKWQKF26SL + Uz355JMvZQ/smgmU9sZRFWowWqDEJ+dmt0MpAoUp0sWpsgd21R7/0MUnP/CJzUU3LY5YYS0CpSyBwlTp + 4lTZg7tam0D58W9+2/YJEjs70+Y4BcTSBEpZj9z74H2bp3K6T4FD6eJU2QO8Vj/x999+5ckiVtodR1VY + Qnx5XvZ60iuBQm3SxamyB3lN4v0nj3/w8YsH/uH3pU+YIFTaHrHCXARKWQKFU6SLU2UP9Jo8/tjjF+/8 + 1u9PnzCHxEq789yjnxQrFDVaoIS4ztltUYJA4VTp4lTZA70Wj3/ggxc/+W3/NX3CXCd2dLHDM22OUKEE + gVKWQOEc6eJU2YO9Ch98/OJ//KMfSJ8wUziq0vaIFU4lUMrbTLr/gCnSxamyB/ya4qPuP/iBD1781D/+ + wfTJciyx0u44BcQpsteVns0dKHdfuHPP5umY7j9ginRxquxBv6ZtoPyTH0qfLKcSKm2PUGGqeONo9rrS + K4FCC9LFqbIH/lo++P4PXvz0P/vh9MlSglhpe8QKNxktUOb+uHuBQinp4lTZg38Njz362MXP/PMfSZ8s + JcWOzhtr2x2ngMgIlLIECiWli1NlT4ClPfa+D1z8z3/xo+mTZS6OqrQ9QoUdgVKWQKG0dHGq7EmwpAiU + //UdP5Y+WZYgVtoesTI2gVKW7+NhDuniVNkTYSmPvfcDF+/6V/enT5YlCZX2R6yMZ7Tv4xEotCpdnCp7 + MiwhftT4S1/60t+IJ0b2hFmDWGl7hMo4BEpZAoU5pYtTZU+IpexfjlpiJXZ03ljb9oiVvgmUsgQKc0sX + p8qeFEs5vCyOqpiSI1b6I1DKEigsIV2cKntiLOXwsuyIFVNqhEo/BEpZAoWlpItTZU+OpRxelkO1xIpQ + aX/ESttGC5T4qaXsdihFoLCkdHGq7AmylMPLknFUxZQcsdIegVKWQGFp6eJU2ZNkKYeX5SY1HVXxxtq2 + R6i0Q6CUJVBYQ7o4VfZEWcrhZZmiplgxbY9YqZtAKUugsJZ0carsybKUw8syVS2hEsRK+yNW6jNaoITs + dihFoLCmdHGq7MmylMPLcixHVUypESr1GDFQ7n/TW9PbogSBwtrSxamyJ8xSDi/LqcSKKTViZV0CpaxH + 7n3wvs3DOn3dhKWki1NlT5qlHF6Wc9QUKt5Y2/6IleXFzjp7neiZQGEE6eJU2RNnKYeXpQRHVUypifvw + XW9+R3r/UpZAKUugUJN0carsybOUw8tSklgxpcZRlXmNGChzfpqsQKE26eJU2RNoKYeXpbQIlXjCZk/k + JQmVPkaslCdQyhIo1ChdnCp7Ei3l8LLMxVEVU2riPnQKqAyBUpZAoVbp4lSf+MQn3pM9mabY/N73PfHE + E+k/m+LwssythliJnZw31rY/jqqcR6CUt5n0dQ/Wli4u4Stf+cqf3Dz5vvr444+nT8rbHP55S3AKyJQc + sXKa7PWgZ3MHyt0X7tyzeTimr3mwtnRxKa+88sqfeuKJJ17Onpi3OfyzluQUkCk1cWRMrEwXH/+evR70 + SqAwunRxSV/+8pe//qmnnvpC9gS9yeGfs4ZaTgGZ9keo3E6glCVQaEG6uLS7d+/++aeffvoz2RP1Ood/ + xlriiS5WTKkRKzmBUpZAoRXp4hpefvnlv/TMM8/8dvaEzRz+/rV5Y60pNU4BXSZQyhIotCRdXMtLL730 + Vz7ykY88mz1xDx3+3lo4qmJKjVARKKXF69PmoZW+dkGN0sU1felLX/rGj370o09nT+B9h7+vJk4BmZIz + aqyM9oWBEWTZ7VCKQKFF6eLaXnzxxb/5sY99bPO8zZ/M4fD31EiomJIzUqwIlLIECq1KF2vwwgsvfNPH + P/7x92VP6HD479dMrJhSM0KoCJSyBAotSxdr8cUvfvFbnn322XdnH/h2+O+2YO1YiR2cN9b2Mb3GikAp + S6DQunSxJp///Oe/LXsz7eG/1wpHVUzJ6SlWRguUkN0OpQgUepAu1uZzn/vcP92Eykf3n9yH/05rxIop + NT2EyoiBEt9BlN0WJQgUepEu1uizn/3sd+z/1M/hP2/V2rEiVPqZVmNFoJQlUOhJulirz3zmM2/5+Mc/ + /mQ8yQ//WcscVTElp6VYEShlCRR6ky7W7Pnnn/+eeKIfrveghqMq3ljbx7QQKgKlLIFCj9LF2r3yyit/ + OlvvRQ2xYvqYWmNlxECZ89NkBQq9ShdZ39qhEsRKP1NTrAiUsgQKPUsXqYejKqbU1BAqo30XT5gzUB65 + 98H7Nndt+toBPUgXqY9YMaVmjViJ92JkO/DeCRQ4T7pIndYOlXe9+R3eWNvRLBErEScjHj0JAgXOly5S + N0dVTMmZI1ZGjpMgUKCMdJE2iBVTcuL+PCdYdmEycpwEgQLlpIu0I0IlXriyF7QlCJU+J07r7aLlgW9+ + +zZAMvGTOqNHyb45AyVsJn0dgF6li7THURUz1zz77LPpDpnL5g6Uuy/cuWdzd6TPf+hVuki71owVb6zt + c0TK7QQKzCNdpG1OAZmSI1JuFqe7sudBKQKFkaWL9MEpIFNiRMr1BArMK12kL2vGilBpf0RKTqDA/NJF + +uMUkDl1RMpVAgWWkS7SL2+sNceOSLkqe3yXEs/Rzc2ePn9hNOki/XMKyEwdkXJZfD5M9rguQaDAZeki + Y4hDymLF3DYi5Q0CBZaVLjIWoWJuGpHyKoECy0sXGZNYMdmIFIECa0kXGdeap4C8sbbOGT1S5vw0WYEC + N0sXwVEVs5uRI0WgwLrSRdgRK2bUSBEosL50EQ6tFStCZf0ZMVIECtQhXYSMoypjzmiRIlCgHuki3GSt + WPHG2nVmpEgRKFCXdBGmWCtWHFVZdkaJFIEC9UkXYaq1QiWIlWVmhEiZM1Diiz03N2P6/AFuli7CsRxV + 6Xd6jxSBAvVKF+FUYqW/6TlSBArULV2Ec6wVKt5YO8/0GikPP/BQ+jgqQaBAGekilOCoSh/TY6QIFGhD + uggliZW2p7dImTNQwmbS5wFwvHQRShMq7U5PkTJ3oMQXdG5usvQ5ABwvXYS5iJX2pqdIuf9Nb00fHyUI + FCgvXYS5rREr3lh72vQSKQIF2pMuwhIiVOJNhtmL/pwcVTlueogUgQJtShdhSU4B1T2tR4pAgXali7CG + NWJFqNw+LUfKnIESj9fNzZM+loEy0kVYi1NA9U2rkeILA6F96SKsbY2jKt5Ym0+LkSJQoA/pItRijVhx + VOXytBYpAgX6kS5CTeLNiWJlvWkpUgQK9CVdhBoJlXWmlUgRKNCfdBFqJlaWnRYiRaBAn9JFqN0ap4BG + fWNt7ZEiUKBf6SK0wlGV+afmSBEo0Ld0EVojVuabWiNFoED/0kVo1dKxMkKo1BgpDz/wUHp/lCBQoB7p + IrTMUZWyU1ukCBQYR7oIPVg6Vnp9Y21NkTJnoMTXMWyubvpYAtaRLkJPnAI6b2qJFIEC40kXoTdOAZ0+ + NUSKQIExpYvQK0dVjp8aIuX+N701vX3PJVCgbuki9E6sTJ+1I0WgwLjSRRiBN9ZOmzUjRaDA2NJFGImj + KjfPWpEyV6CE+FqFzVVLHw9APdJFGJFYyWeNSJnz02QFCrQjXYRRCZWrs3SkCBRgJ12E0YmVN2bJSBEo + wL50EXjVkrFS6xtrl4oUgQIcSheBN0SoxE+DZDu/OdR2VGWJSBEoQCZdBK4a9RTQ3JEyZ6DEfba5Cun9 + CdQvXQSut2Ss1BAqc0aKQAFuki4CNxvpFNBckSJQgNuki8A0Sx5ViTfWrhErc0SKQAGmSBeB4ywZK0uH + SulIESjAVOkicLzYQfZ4CqhkpDz8wEPpdSlBoEB/0kXgdL0dVSkVKQIFOFa6CJyvl1gpESkCBThFugiU + ER8ktlSszPXG2nMjRaAAp0oXgbJaPqpybqRkl7EEgQL9SxeBebQYK+dEyv1vemt62c4lUGAM6SIwnyVP + AZUIlVMjRaAA50oXgfm1clTllEiZK1DiR7w3Fym9PYH+pIvAcpaKlVPfWHtspAgUoJR0EVheraeAjomU + uT5NVqDAmNJFYB01ngKaGikCBSgtXQTWVdNRlSmRIlCAOaSLQB1qiJXbImXOLwzcTHq7AGNIF4F6rP3G + 2psiZc5AiR/V3vz16W0CjCFdBOqz1lGV6yJFoABzSxeBei0dK1mkCBRgCekiULclQ+X555+/FCiP/ex7 + 0n+3BIEC7EsXgTYsFSsRJs88/pRAARaVLgJtWSpW5hKXP7tewNjSRaA9rYaKQAGuky4C7WopVgQKcJN0 + EWhf7bEiUIDbpItAHyIE4qPls0hYk0ABpkgXgb7UdFTFT/EAU6WLQJ/WjJU4oiNQgGOki0C/1jgF5PQO + cIp0EejfEkdVIoayvxtginQRGEfESslgiTCJP8+pHeBc6SIwpoiLU04Fxe8JwgQoKV0EiOAIuyMth3b/ + PPu9AOe7+Lr/Dx9K5BSknwTlAAAAAElFTkSuQmCC + diff --git a/source-code/source/plugins/Patches/PatchApplier710.h b/source-code/source/plugins/Patches/PatchApplier710.h index 6c93cce..b692d88 100644 --- a/source-code/source/plugins/Patches/PatchApplier710.h +++ b/source-code/source/plugins/Patches/PatchApplier710.h @@ -678,5 +678,16 @@ class PatchApplier710 : public PatchApplier { InjectCode((void*)(0x14050294d), { 0x89, 0x01 }); // MOV dword ptr [RCX], EAX InjectCode((void*)(0x14050294f), { 0xc3 }); // RET } + + // lag compensation + if (nLagCompensation>0 && nLagCompensation<50) + { + 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 + float startPos = (float)nLagCompensation / 100.0; + 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); + } } }; \ No newline at end of file diff --git a/source-code/source/plugins/Patches/framework.h b/source-code/source/plugins/Patches/framework.h index 2e28c4e..74cc19a 100644 --- a/source-code/source/plugins/Patches/framework.h +++ b/source-code/source/plugins/Patches/framework.h @@ -125,4 +125,5 @@ auto nNoDelete = GetPrivateProfileIntW(L"patches", L"prevent_data_deletion", FAL auto nReflectResWidth = GetPrivateProfileIntW(L"graphics", L"reflect_res_width", 512, CONFIG_FILE); auto nReflectResHeight = GetPrivateProfileIntW(L"graphics", L"reflect_res_height", 256, 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); \ No newline at end of file +auto nRefractResHeight = GetPrivateProfileIntW(L"graphics", L"refract_res_height", 256, CONFIG_FILE); +auto nLagCompensation = GetPrivateProfileIntW(L"graphics", L"lag_compensation", 0, CONFIG_FILE); \ No newline at end of file