From 90f03dc4168483c12777f65fc6985343bac71d68 Mon Sep 17 00:00:00 2001 From: gho tik Date: Thu, 19 Jan 2017 11:49:37 -0500 Subject: [PATCH] v2_04_06_src_fx3 Former-commit-id: e06430d1b07aa1f28da76b2503298dd67ae349f9 --- build/dxwnd.dll | 2 +- build/dxwnd.exe | 2 +- ...zardry Chronicles V0984b - English.exe.dxw | 36 ++++++ build/exports/Wizardry Chronicles.dxw | 36 ++++++ build/readme-relnotes.txt | 7 +- dll/dxwnd.cpp | 2 +- dll/dxwnd.vs2008.suo | Bin 564224 -> 564224 bytes dll/hd3d7.cpp | 112 ++++++++++++------ dll/kernel32.cpp | 11 +- host/dxwndhost.aps | Bin 260200 -> 260432 bytes host/dxwndhost.rc | Bin 149810 -> 149808 bytes host/dxwndhost.vs2008.suo | Bin 169472 -> 168960 bytes ...st.vs2008.vcproj.DESKTOP-Q3RE27J.user.user | 65 ---------- 13 files changed, 165 insertions(+), 108 deletions(-) create mode 100644 build/exports/Wizardry Chronicles V0984b - English.exe.dxw create mode 100644 build/exports/Wizardry Chronicles.dxw delete mode 100644 host/dxwndhost.vs2008.vcproj.DESKTOP-Q3RE27J.user.user diff --git a/build/dxwnd.dll b/build/dxwnd.dll index 763a8a5..d6660b5 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8f543c951f150e29ae64f702c21bceeaa46d3bda294913e9b03346aa6aa276ea +oid sha256:c4a337db3a9c5cbb7c06069a437f34c28285dcf2548181622789c594c8750bc1 size 781312 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 470de73..7abf7ae 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:864a303e49a88b3bee7353573304b29f4b64852f8fae83b8ac33502099c46a08 +oid sha256:fb594ca522bdf3bc9956b3e2f18c8582c85728c30a77f6c0879e971bc3417ff2 size 673280 diff --git a/build/exports/Wizardry Chronicles V0984b - English.exe.dxw b/build/exports/Wizardry Chronicles V0984b - English.exe.dxw new file mode 100644 index 0000000..9018488 --- /dev/null +++ b/build/exports/Wizardry Chronicles V0984b - English.exe.dxw @@ -0,0 +1,36 @@ +[target] +title0=Wizardry Chronicles V0984b - English.exe +path0=D:\Games\Wizardry Chronicle\Wizardry Chronicles V0984b - English.exe +startfolder0= +launchpath0= +module0= +opengllib0= +notes0= +registry0= +ver0=0 +monitorid0=-1 +coord0=0 +flag0=673185826 +flagg0=1207959552 +flagh0=20 +flagi0=205520900 +flagj0=4224 +flagk0=65536 +flagl0=0 +flagm0=0 +tflag0=0 +dflag0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=0 +swapeffect0=0 +maxddinterface0=7 +slowratio0=2 +scanline0=0 +initresw0=800 +initresh0=600 diff --git a/build/exports/Wizardry Chronicles.dxw b/build/exports/Wizardry Chronicles.dxw new file mode 100644 index 0000000..fa9d3c3 --- /dev/null +++ b/build/exports/Wizardry Chronicles.dxw @@ -0,0 +1,36 @@ +[target] +title0=Wizardry Chronicles +path0=D:\Games\Wizardry Chronicle\Wiz.exe +startfolder0= +launchpath0= +module0= +opengllib0= +notes0= +registry0= +ver0=0 +monitorid0=-1 +coord0=0 +flag0=673185826 +flagg0=1207959552 +flagh0=20 +flagi0=138412036 +flagj0=4224 +flagk0=65536 +flagl0=0 +flagm0=0 +tflag0=0 +dflag0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=0 +swapeffect0=0 +maxddinterface0=7 +slowratio0=2 +scanline0=0 +initresw0=800 +initresh0=600 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index f8a7cad..86cc913 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -1455,10 +1455,13 @@ add: GDI32 debug highlighting of blitted rects on screen add: hooks for GDI32 GetTextExtentPointA and GetTextExtentPoint32A: needed for proper string rendering on "Warhammer: Shadow of the Horned Rat" add: hook for GDI32 GdiAlphaBlend, very rare call that appeared in "RHEM" during savegame load. -v2.04.06 +v2.04.06/fx3 GUI: add: Expert mode DLL: fix: corrected condition to print two virtual registry log messages fix: improved logic to recover surfaces with DDSCAPS_TEXTURE capability - ref. "Dominant Species" -fix: fixed cursor clipping state and toggle key to make it work in all conditions \ No newline at end of file +fix: fixed cursor clipping state and toggle key to make it work in all conditions +fix: D3D objects hooking with QueryInterface method. Fixes "Wizardry Chronicle" +fix: add hook for GDI32 GdiGradientFill and GdiTransparentBlt, present in "RHEM" +fix: log messages for CloseHandle wrapper \ No newline at end of file diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index 95c04fe..c0dcbc1 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -27,7 +27,7 @@ along with this program. If not, see . #include "TlHelp32.h" -#define VERSION "2.04.06.fx2" +#define VERSION "2.04.06.fx3" #define DDTHREADLOCK 1 diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index 459a95f77c9450c09e450593f431e254f1970d98..71657df4ffc006b430f41235e264dff8a872472d 100644 GIT binary patch delta 230 zcmZqJq13QLX+sVRn}eT`b#Bq-B9=a8fd|J*Dxx<0a9?;j^O;)BcbmzLoCb>>I2fmY z<6{!p9KyMZYx*>GHmS)I%-JT(i6}5KY_=ESJ1$K{zJfajaK#> zJ{&+ZKtOHsh1mv^?+S5DQ($t~-f)Tifa1iGgzXEyuqUu?Z}`RDz&ibaE>pwwpk#KV P=?0hBWw!cpY?=)K6uwt| delta 279 zcmZqJq13QLX+sVR+X8K+Z>I}47qRp)3)IHpu)y8Sx!WOv1GHo2qy=l&Gdx(1U7i9AIGNI0FV1ybN~PV diff --git a/dll/hd3d7.cpp b/dll/hd3d7.cpp index fd30ed1..05051a1 100644 --- a/dll/hd3d7.cpp +++ b/dll/hd3d7.cpp @@ -702,51 +702,91 @@ void HookTexture(LPVOID *lpTexture, int version) } } -HRESULT WINAPI extQueryInterfaceD3(int d3dversion, QueryInterfaceD3_Type pQueryInterfaceD3, void *lpd3d, REFIID riid, LPVOID *ppvObj) +HRESULT WINAPI extQueryInterfaceD3(int d3dversion, QueryInterfaceD3_Type pQueryInterfaceD3, void *lpd3d, REFIID riid, LPVOID *obp) { HRESULT res; + unsigned int dwLocalDDVersion; + unsigned int dwLocalD3DVersion; - OutTraceD3D("QueryInterface(D3D%d): d3d=%x REFIID=%x obj=%x\n", d3dversion, lpd3d, riid.Data1, ppvObj); - res=(*pQueryInterfaceD3)(lpd3d, riid, ppvObj); - if(res){ - OutTraceE("QueryInterface(D3D) ERROR: err=%x(%s)\n", res, ExplainDDError(res)); + res = (*pQueryInterfaceD3)(lpd3d, riid, obp); + OutTraceDDRAW("QueryInterface(D3D%d): lpdd=%x REFIID=%x(%s) obp=%x ret=%x at %d\n", + d3dversion, lpd3d, riid.Data1, ExplainGUID((GUID *)&riid), *obp, res, __LINE__); + + if(res) { + OutTraceE("QueryInterface(D3D) ERROR: res=%x(%s)\n", res, ExplainDDError(res)); return res; } - switch(d3dversion){ - case 1: - SetHook((void *)(**(DWORD **)ppvObj + 12), extInitialize, (void **)&pInitialize, "Initialize"); - SetHook((void *)(**(DWORD **)ppvObj + 16), extEnumDevices1, (void **)&pEnumDevices1, "EnumDevices"); - SetHook((void *)(**(DWORD **)ppvObj + 20), extCreateLight1, (void **)&pCreateLight1, "CreateLight(1)"); -#ifdef TRACEMATERIAL - SetHook((void *)(**(DWORD **)ppvObj + 24), extCreateMaterial1, (void **)&pCreateMaterial1, "CreateMaterial(1)"); -#endif - SetHook((void *)(**(DWORD **)ppvObj + 28), extCreateViewport1, (void **)&pCreateViewport1, "CreateViewport(1)"); - SetHook((void *)(**(DWORD **)ppvObj + 32), extFindDevice1, (void **)&pFindDevice1, "FindDevice(1)"); + + dwLocalDDVersion=0; + dwLocalD3DVersion=0; + switch(riid.Data1){ + case 0x6C14DB80: //DirectDraw1 + dwLocalDDVersion = 1; break; - case 2: - SetHook((void *)(**(DWORD **)ppvObj + 12), extEnumDevices2, (void **)&pEnumDevices2, "EnumDevices(2)"); - SetHook((void *)(**(DWORD **)ppvObj + 16), extCreateLight2, (void **)&pCreateLight2, "CreateLight(2)"); -#ifdef TRACEMATERIAL - SetHook((void *)(**(DWORD **)ppvObj + 20), extCreateMaterial2, (void **)&pCreateMaterial2, "CreateMaterial(2)"); -#endif - SetHook((void *)(**(DWORD **)ppvObj + 24), extCreateViewport2, (void **)&pCreateViewport2, "CreateViewport(2)"); - SetHook((void *)(**(DWORD **)ppvObj + 28), extFindDevice2, (void **)&pFindDevice2, "FindDevice(2)"); + case 0xB3A6F3E0: //DirectDraw2 + dwLocalDDVersion = 2; break; - case 3: - SetHook((void *)(**(DWORD **)ppvObj + 12), extEnumDevices3, (void **)&pEnumDevices3, "EnumDevices(3)"); - SetHook((void *)(**(DWORD **)ppvObj + 16), extCreateLight3, (void **)&pCreateLight3, "CreateLight(3)"); -#ifdef TRACEMATERIAL - SetHook((void *)(**(DWORD **)ppvObj + 20), extCreateMaterial3, (void **)&pCreateMaterial3, "CreateMaterial(3)"); -#endif - SetHook((void *)(**(DWORD **)ppvObj + 24), extCreateViewport3, (void **)&pCreateViewport3, "CreateViewport(3)"); - SetHook((void *)(**(DWORD **)ppvObj + 28), extFindDevice3, (void **)&pFindDevice3, "FindDevice(3)"); + case 0x618f8ad4: //DirectDraw3 + dwLocalDDVersion = 3; break; - case 7: - SetHook((void *)(**(DWORD **)ppvObj + 12), extEnumDevices7, (void **)&pEnumDevices7, "EnumDevices(7)"); - SetHook((void *)(**(DWORD **)ppvObj + 32), extCreateDevice7, (void **)&pCreateDevice7, "CreateDevice(D3D7)"); + case 0x9c59509a: //DirectDraw4 + dwLocalDDVersion = 4; + break; + case 0x15e65ec0: //DirectDraw7 + dwLocalDDVersion = 7; + break; + case 0x3BBA0080: //Direct3D + dwLocalD3DVersion = 1; + break; + case 0x6aae1ec1: //Direct3D2 + dwLocalD3DVersion = 2; + break; + case 0xbb223240: //Direct3D3 + dwLocalD3DVersion = 3; + break; + case 0xf5049e77: //Direct3D7 + dwLocalD3DVersion = 7; break; } - return res; + if (! *obp){ + OutTraceDDRAW("QueryInterface(D): Interface for DX version %d not found\n", dwLocalDDVersion); + return(0); + } + if(dwLocalDDVersion) OutTraceDW("QueryInterface(D): Got interface for DX version %d\n", dwLocalDDVersion); + if(dwLocalD3DVersion) OutTraceDW("QueryInterface(D): Got interface for D3D version %d\n", dwLocalD3DVersion); + + if (dwLocalDDVersion > dxw.dwMaxDDVersion) { + *obp = NULL; + OutTraceDW("QueryInterface(D): lpdd=%x REFIID=%x obp=(NULL) ret=%x at %d\n", + lpd3d, riid.Data1, res, __LINE__); + return(0); + } + + switch (dwLocalDDVersion){ + case 1: // you never know .... + case 2: + case 3: + case 4: + case 7: + dxw.dwDDVersion=dwLocalDDVersion; + extern void HookDDSession(LPDIRECTDRAW *, int); + HookDDSession((LPDIRECTDRAW *)obp, dxw.dwDDVersion); + break; + } + + switch (dwLocalD3DVersion){ + case 1: + case 2: + case 3: + case 7: + HookDirect3DSession((LPDIRECTDRAW *)obp, dwLocalD3DVersion); + break; + } + + OutTraceDDRAW("QueryInterface(D3D): lpdd=%x REFIID=%x obp=%x DDVersion=%d ret=0\n", + lpd3d, riid.Data1, *obp, dxw.dwDDVersion); + + return D3D_OK; } HRESULT WINAPI extQueryInterfaceD31(void *lpd3d, REFIID riid, LPVOID *ppvObj) @@ -924,7 +964,7 @@ HRESULT WINAPI extEnumDevices(int d3dversion, EnumDevices_Type pEnumDevices, voi HRESULT res; CallbackArg Arg; - OutTraceD3D("EnumDevices(D#D%d): d3d=%x arg=%x\n", d3dversion, lpd3d, arg); + OutTraceD3D("EnumDevices(D3D%d): d3d=%x arg=%x\n", d3dversion, lpd3d, arg); Arg.cb= &cb; Arg.arg=arg; res=(*pEnumDevices)(lpd3d, (LPD3DENUMDEVICESCALLBACK)extDeviceProxy, (LPVOID)&Arg); diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index ded25e8..a0b7e96 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -954,8 +954,15 @@ HANDLE WINAPI extCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwS BOOL WINAPI extCloseHandle(HANDLE hObject) { BOOL ret; - OutTrace("CloseHandle: hFile=%x\n", hObject); - if (hObject && (hObject != (HANDLE)-1)) __try {ret=CloseHandle(hObject);} __except(EXCEPTION_EXECUTE_HANDLER){}; + if (hObject && (hObject != (HANDLE)-1)) { + OutTraceB("CloseHandle: hFile=%x\n", hObject); + __try {ret=CloseHandle(hObject); + } + __except(EXCEPTION_EXECUTE_HANDLER){}; + } + else{ + OutTraceDW("CloseHandle: BYPASS hFile=%x\n", hObject); + } return ret; } diff --git a/host/dxwndhost.aps b/host/dxwndhost.aps index ac4a258dd6d1af6690c76492f8c53638a16e391a..ae3a3aaab56a6a05b00d0d2cabdf1fa13d56a1cf 100644 GIT binary patch delta 1841 zcmX|=dr;I>6vuz}URZ5Wz|v7s9s;gt0_s{ZMI+N_>6TOuCYep>A2cQ@@-S>%i9M&8atQv{&wcK-~D{gIp1@CcV=(& zhP3sElti(l9g|{&(ww|>^_=Yq|JC=`S6X52ixq8zElTc2!esfbH zQ&bLxn=2L6>Zx0jj8dCk_Q_I%9zbwzy1$WY3_@}(;K+?vqa*Yixs#1%3&iHFP^DQ= zmN!qq^Kd`!f`Wzm-=F1kMH}@`^S?79cIhc!{HAKWkwMAU2z_DEhst8z`uP&CK@s{{ zup7h4`sS|&j9M1t@1E`7!q;+2O43K}*=E$sbl1LT4LYUYFFWH;8V8pujH7qLOuGU7 zu-*Q;I{5<_u%{~Ediwr5>Lff?KzZI+_~^h4RiCb(KJZkaqK$f&v(wn^hVIHYRB10P zcBx~tePDOZ^jDz5WrjYNMKzW|Le(r)i?4bDHdjqiwF)?1m8fc-Dl=G5kAiS_n5yrG zRQGcV4nnD0ZG?SpGxWOSRLup6)y4r5s?D&a+F0U-`f6jz@#-K5u9>XnYQR=w)E3kP z!Cs>V#e`l1nGO?cjn)aZL6B8z#2f}^ZIVCJkjtjF!WZk=+Dz#j2?a@-6aa=uq3>G zOH5&Q9O)A=%!xC7A~LXjuBOe!#q`ru$~0~M3Ebcl(R}zxESDPf6NH_KK(9{(3~PLe z(Gdf%bwG^S)g=PNvR4?s^D-NcQAFIi04-f2LX_AT7B3(-L%M0NVWxCLQyGRVB-bt{ zQ;6nBYLJvov__Jbhz;WPE)gk`moR+cEi$9JDdyS|v~*KU%2FD9o7@a?Me+*jSx&S? z()9NkKAlNqm-Hx`;lnjV4U#!BLM=(>muG0)FPsv>ACN<-?(v51P#1{6VDQ=>s zZT%I^eH7HxkJF@%{ugbeVwuKqRi6mwjuBWu2J_+feRQ#*Q#ppj@vy)Vnzrs;?36Q} zm1yp#mO-4_FCzKuY_v&ygexTuFTw&s(YBXk>mEMdly|RlFt7J6QmCJVd|g=`wyL0o1*{# delta 1991 zcmZuxdr*{B6#wqMJRFwRwZv&Ld1yS!c%)m=sFOJwn7ZN&shO4fM`NR+mgA67>VS#y z_NpgxLoA#K*av)xr6^Q7QzIA{nHZWgI>v}BizwR2MCaVkow4H1-0yeJ`JLbIz82bU zj_&r2E{S5c(&$N|xkt!;_jp;qV_aQ!<$FxX=q(wPvB&h1EiVfdZj>ckX6w&?n8s9k zKsvV8sHk3FwJpUcw(EztFH<4Er^)i1Sh*a75B@|TD2MG zknv7+OY*ogM1J6mReZTT;hdtP1JdM5qDYpzLgX7RgFh$_xD5U0((8Io@kQ}#Y4o>;I+js|;jPoQb{+P!kvpq42_sB+%vBJVSleE;Ssw~5JnGrKxep+XA zB-ERv_kQ)TOsrScpoW0Qwc%m;_erbVS0AoSkIU2bYFn&LPSD>`wQps$u9jy<_1k)q ziS3awO-uCLrnGA;<4EfvwkVjT!UQLa-Z|6BaPlKFouc3cW`ounB91vqw?_tL2~Dfq zEI-~H5h!MB+Dw?yDx*PA1PaT04_vkfmW}G>OXZ=(VD6)~ zS0RxwVn`*A1S$E0KE&Uu_VakhIR4A~j&W#e4L`cUc6~j1kt!w95HtIyO!7|Ab?)(zS++ÐJ z!s4j#=z3Ma;x;8nMic*-h(T8YhZ?+)U`jmI9JbbALdr%wT|S;Jm6C5-{5D0H;rl;e zL;Tn3z-C;gctqagMd!Zz&b4^D_l03xWibvjJiL2EVWm1S8Oss*iYWrtPZidxm0qO;lX*6g02PBGK(t|&k6B>_3*lwHQm rO_>KXo_7fv?&2cxf517y+$%7MC{|n(kn|^ZCI5w*s2%}*J;M4Aeh8wj diff --git a/host/dxwndhost.rc b/host/dxwndhost.rc index 650888347f59cdb3501ecf6966c0d0bfcc3cd392..4d096485673c51493273992e91075998a7a1e4fe 100644 GIT binary patch delta 26 icmdlqiF3mw&W0_FR_V;f3`Wxz$}x#<4@qad_YeSn3JG=q delta 33 pcmdlmiF4B=&W0_FR_Uzn48{yb(=VDZiB3;RW0csQmCktVAppN93w;0p diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index bd880066053c7b9497455e6ce8833b6299fedf09..aef3c0295f94e92939300805079bed7f54ec3b47 100644 GIT binary patch delta 1197 zcma)6T})h65T2QPcir6rUA7Bd5tc3CFHN!gQz%F+%Tn40vC6(#YeEqb2(h?QBrVjN z)EW|tft-ekwGZ2dP#$X2u*$8858L4Ph7}GR_5@UEWRiT9ksdHD;=$mu$-7|M) z&bc$+oO6xqE@Rqtb4|l@YF&HR-dDft@yUcr=&h>B7E(c7R~z~ZPV@r6V-Ze9s6@I>4f_i^HcfGc029R)amVKF`#z2 zBP#0l3SvZ{M%;y|qPw=5&W{xU@h_d0T_yO{uOg~R9tMs1;EW0JOqe~L|w*)RMrNR&H=HeHe zP56WDmYCz_eZpd!YM-y^^daLMR&Y9j_LqlX2+qJEsDr~$3;Q7k)zA!8f)E77 zUIqI^YtCpfvBV%Ewpxj@;zKeTMQap)vpk1^v559^-;e0MmhMH0{=Xhr{jl&KiQ^e) zoH~ifD=7?^ffigw)i+;|X^O>Uz>N0^le7I8b*oKJ6noWgb0L1Kj(jZ9rRJ~iV|=hg z@@tZ;ho#a3@FH}>JMg;Lx}g`|5dEM~hXeG9CREIB;etNiQOgdE3dcL{&FYk<6B&Yn z8A=+Z@Fu7c3M?Y3g*Jx!m=VPKJYtSKMYj;UxY0@b*|UfR*0n0&Nhjs=J*QN5*GZid17w(K7k$=h|5$jt4t)9* zDmRnIsS@$ICzr`wdyQI%ulmTN7M^wSA}nR7b|&1RsaA1 delta 1503 zcmY*ZZA@Eb6u#&5(zRVF9drdd=sGOjg6Noh@W+wTd=@ov1sYBYR5jh@%3TRr8kJH+sZ_#u8ZIGz2d4~CgL{TIFfM! z-LD=P=$X0YjJ}cB(lgQ96rqMZ*eYslS0HSFy~m1cG;uVm7j&`7T`r<-4`Y{K(`J`u zmK6ZB|HU^SS7aNb?wb|}6HLNpI@1O|Bk8eO^kohjEyqHh#A+<$#xvkG@p8eG6{@%d z((Pw)BQH6PZhyZOE{Io77a9JdqC@F{y9b`MLKf$F{>xh!_$5bQ;;P0^@6W9rZ1xz_ zpE!L^)n_HnPvVx+^nlYAMeDWCEp6z~wB_Y-)K+G%99Y!TNqh;svuK3pZmfgjl!_00K1cgnCL< zVF`6!2hUitgPVQO#j8z+c%WD&1jcX*fLdCxf?`jhUp98}xHNwlqB3fOB#7QgmvnVQ z*iG?Fh*DPpz9eV*q45YsTQEuC8vgvhJq-`Y*b;Q=mD_lyA7pH2R5DhEtY-ZXV<#iR zs9{7IwT#CZWV2wtUcqXx`G-q7CXwRV5Qi?h;=sq`i8Xi`AV#%z+)nx=1Sx3)8=bYI z*IvaB@n6L?&e*Yx7VKCjQi)=ks(}&_yQ|aw90TJlcfy0M-BgU~=I( ztV2;4Di(Fef;5%GeZL##H~Z`!^wP;%@YBI&+)o&RJ!0Pn$~oqrUE zrS)~}07?cSNi7j5q0z4(EJp8GW$TN0vzR>3fSazr4aGDU0pHO5L5R>`HtZ0+V_vcE zu7{qFK&nsE?&G&9cWUW>b_452ScjSSm|iC9KiBeweaRZN(kO8C - - - - - - - - - -