From bb88830a5be732ab3dbd04e52cc795b1480b1166 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Sun, 12 Sep 2021 13:59:58 +0800 Subject: [PATCH] Added a fix to display the color index 255 of the palette correctly * in DX9 mode when using the hi-res patch Some minor code corrections. --- artifacts/ddraw.ini | 4 +- artifacts/scripting/headers/sfall.h | 2 + sfall/Modules/Graphics.cpp | 138 ++++++---------------------- sfall/Modules/Graphics.h | 90 ++++++++++++++++++ sfall/Modules/SpeedPatch.cpp | 16 ++-- 5 files changed, 132 insertions(+), 118 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index c5a91864..6d4d7bd2 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -61,8 +61,8 @@ GraphicsWidth=0 GraphicsHeight=0 ;Window position data. Do not modify -;Set to 0 to reset if the window position is incorrect -WindowData=0 +;Set to -1 or 0 to reset if the window position is incorrect +WindowData=-1 ;Uncomment the option to use a hardware shader (requires DX9 graphics mode) ;The shader file .fx must be placed in \\shaders\ and must contain one technique with one or more passes diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 83ba8cd4..2baca3ac 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -343,6 +343,7 @@ #define get_text_width(text) sfall_func1("get_text_width", text) #define has_fake_perk_npc(npc, perk) sfall_func2("has_fake_perk_npc", npc, perk) #define has_fake_trait_npc(npc, trait) sfall_func2("has_fake_trait_npc", npc, trait) +#define hide_win sfall_func0("hide_window") #define hide_window(winName) sfall_func1("hide_window", winName) #define interface_art_draw(winID, artFile, x, y) sfall_func4("interface_art_draw", winID, artFile, x, y) #define interface_art_draw_frame(winID, artID, x, y, frame) sfall_func5("interface_art_draw", winID, artID, x, y, frame) @@ -393,6 +394,7 @@ #define set_unique_id(obj) sfall_func1("set_unique_id", obj) #define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time) #define set_window_flag(winID, flag, value) sfall_func3("set_window_flag", winID, flag, value) +#define show_win sfall_func0("show_window") #define show_window(winName) sfall_func1("show_window", winName) #define spatial_radius(obj) sfall_func1("spatial_radius", obj) #define string_compare(str1, str2) sfall_func2("string_compare", str1, str2) diff --git a/sfall/Modules/Graphics.cpp b/sfall/Modules/Graphics.cpp index fd0a953c..53ad6f3f 100644 --- a/sfall/Modules/Graphics.cpp +++ b/sfall/Modules/Graphics.cpp @@ -35,96 +35,6 @@ namespace sfall typedef HRESULT (__stdcall *DDrawCreateProc)(void*, IDirectDraw**, void*); //typedef IDirect3D9* (__stdcall *D3DCreateProc)(UINT version); -static const char* gpuEffectA8 = - "texture image;" - "texture palette;" - "texture head;" - "texture highlight;" - "sampler s0 = sampler_state { texture=; };" - "sampler s1 = sampler_state { texture=; minFilter=none; magFilter=none; addressU=clamp; addressV=clamp; };" - "sampler s2 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" - "sampler s3 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" - "float2 size;" - "float2 corner;" - "float2 sizehl;" - "float2 cornerhl;" - "int showhl;" - // shader for displaying head textures - "float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {" - "float backdrop = tex2D(s0, Tex).a;" - "float3 result;" - "if (abs(backdrop - 1.0) < 0.001) {" // (48.0 / 255.0) // 48 - key index color - "result = tex2D(s2, saturate((Tex - corner) / size));" - "} else {" - "result = tex1D(s1, backdrop).bgr;" // get color in palette and swap R <> B - "}" - // blend highlights - "if (showhl) {" - "float4 h = tex2D(s3, saturate((Tex - cornerhl) / sizehl));" - "result = saturate(result + h);" // saturate(result * (1 - h.a) * h.rgb * h.a)" - "}" - "return float4(result, 1);" - "}" - "technique T1" - "{" - "pass p1 { PixelShader = compile ps_2_0 P1(); }" - "}" - - // main shader - "float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {" - "float3 result = tex1D(s1, tex2D(s0, Tex).a);" // get color in palette - "return float4(result.bgr, 1);" // swap R <> B - "}" - "technique T0" - "{" - "pass p0 { PixelShader = compile ps_2_0 P0(); }" - "}"; - -static const char* gpuEffectL8 = - "texture image;" - "texture palette;" - "texture head;" - "texture highlight;" - "sampler s0 = sampler_state { texture=; };" - "sampler s1 = sampler_state { texture=; minFilter=none; magFilter=none; addressU=clamp; addressV=clamp; };" - "sampler s2 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" - "sampler s3 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" - "float2 size;" - "float2 corner;" - "float2 sizehl;" - "float2 cornerhl;" - "int showhl;" - // shader for displaying head textures - "float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {" - "float backdrop = tex2D(s0, Tex).r;" - "float3 result;" - "if (abs(backdrop - 1.0) < 0.001) {" - "result = tex2D(s2, saturate((Tex - corner) / size));" - "} else {" - "result = tex1D(s1, backdrop).bgr;" - "}" - // blend highlights - "if (showhl) {" - "float4 h = tex2D(s3, saturate((Tex - cornerhl) / sizehl));" - "result = saturate(result + h);" - "}" - "return float4(result, 1);" - "}" - "technique T1" - "{" - "pass p1 { PixelShader = compile ps_2_0 P1(); }" - "}" - - // main shader - "float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {" - "float3 result = tex1D(s1, tex2D(s0, Tex).r);" - "return float4(result.bgr, 1);" - "}" - "technique T0" - "{" - "pass p0 { PixelShader = compile ps_2_0 P0(); }" - "}"; - IDirectDrawSurface* primaryDDSurface = nullptr; // aka _GNW95_DDPrimarySurface static DWORD ResWidth; @@ -152,9 +62,10 @@ static struct PALCOLOR { union { DWORD xRGB; struct { - BYTE B; - BYTE G; BYTE R; + BYTE G; + BYTE B; + BYTE x; }; }; } palette[256]; @@ -168,8 +79,8 @@ static DWORD gHeight; static long moveWindowKey[2]; static bool windowInit = false; -static DWORD windowLeft = 0; -static DWORD windowTop = 0; +static long windowLeft = 0; +static long windowTop = 0; static HWND window; static DWORD windowStyle = WS_CAPTION | WS_BORDER | WS_MINIMIZEBOX; @@ -251,6 +162,14 @@ static void WindowInit() { ScriptShaders::LoadGlobalShader(); } +static void CenterWindow() { + RECT desktop; + GetWindowRect(GetDesktopWindow(), &desktop); + + windowLeft = (desktop.right / 2) - (gWidth / 2); + windowTop = (desktop.bottom / 2) - (gHeight / 2); +} + // pixel size for the current game resolution const float* Graphics::rcpresGet() { return rcpres; @@ -944,16 +863,16 @@ public: HRESULT __stdcall SetEntries(DWORD a, DWORD b, DWORD c, LPPALETTEENTRY destPal) { // used to set palette for splash screen, fades, subtitles if (!windowInit || c == 0 || b + c > 256) return DDERR_INVALIDPARAMS; - __movsd((DWORD*)&palette[b], (DWORD*)destPal, c); + __movsd((DWORD*)&palette[b], (DWORD*)destPal, c); // copy DWORDs if (Graphics::GPUBlt) { SetGPUPalette(); } else { // X8B8G8R8 format for (size_t i = b; i < b + c; i++) { // swap color B <> R - BYTE clr = palette[i].B; - palette[i].B = palette[i].R; - palette[i].R = clr; + BYTE clrB = palette[i].R; + palette[i].R = palette[i].B; + palette[i].B = clrB; } primaryDDSurface->SetPalette(0); // update texture if (FakeDirectDrawSurface::IsPlayMovie) return DD_OK; // prevents flickering at the beginning of playback (w/o HRP & GPUBlt=2) @@ -1059,9 +978,7 @@ public: AdjustWindowRect(&r, windowStyle, false); r.right -= r.left; r.bottom -= r.top; - if (!SetWindowPos(a, HWND_NOTOPMOST, windowLeft, windowTop, r.right, r.bottom, SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_SHOWWINDOW)) { - windowLeft = windowTop = 0; // fail to set position - } + SetWindowPos(a, HWND_NOTOPMOST, windowLeft, windowTop, r.right, r.bottom, SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_SHOWWINDOW); } dlogr(" Done", DL_MAIN); @@ -1108,10 +1025,10 @@ HRESULT __stdcall InitFakeDirectDrawCreate(void*, IDirectDraw** b, void*) { gWidth = dispMode.Width; gHeight = dispMode.Height; } else { - gWidth = IniReader::GetConfigInt("Graphics", "GraphicsWidth", 0); + gWidth = IniReader::GetConfigInt("Graphics", "GraphicsWidth", 0); gHeight = IniReader::GetConfigInt("Graphics", "GraphicsHeight", 0); if (!gWidth || !gHeight) { - gWidth = ResWidth; + gWidth = ResWidth; gHeight = ResHeight; } } @@ -1143,12 +1060,12 @@ HRESULT __stdcall InitFakeDirectDrawCreate(void*, IDirectDraw** b, void*) { } else { moveWindowKey[0] &= 0xFF; } - windowData = IniReader::GetConfigInt("Graphics", "WindowData", 0); + windowData = IniReader::GetConfigInt("Graphics", "WindowData", -1); if (windowData > 0) { windowLeft = windowData >> 16; windowTop = windowData & 0xFFFF; - } else { - windowData = 0; + } else if (windowData == -1) { + CenterWindow(); } } @@ -1215,8 +1132,13 @@ void Graphics::init() { SafeWrite8(0x50FB6B, '2'); // Set call DirectDrawCreate2 HookCall(0x44260C, game_init_hook); - // Patch HRP to show the mouse cursor over the window title - if (Graphics::mode == 5 && hrpVersionValid) SafeWrite8(HRPAddress(0x10027142), CodeType::JumpShort); + if (hrpVersionValid) { + // Patch HRP to show the mouse cursor over the window title + if (Graphics::mode == 5) SafeWrite8(HRPAddress(0x10027142), CodeType::JumpShort); + + // Patch HRP to fix the issue of displaying a palette color with index 255 for images (splash screens, ending slides) + SafeWrite8(HRPAddress(0x1000F8C7), CodeType::JumpShort); + } textureFilter = IniReader::GetConfigInt("Graphics", "TextureFilter", 1); dlogr(" Done", DL_INIT); diff --git a/sfall/Modules/Graphics.h b/sfall/Modules/Graphics.h index 315e6575..74031b2c 100644 --- a/sfall/Modules/Graphics.h +++ b/sfall/Modules/Graphics.h @@ -116,4 +116,94 @@ public: } }; +static const char* gpuEffectA8 = + "texture image;" + "texture palette;" + "texture head;" + "texture highlight;" + "sampler s0 = sampler_state { texture=; };" + "sampler s1 = sampler_state { texture=; minFilter=none; magFilter=none; addressU=clamp; addressV=clamp; };" + "sampler s2 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" + "sampler s3 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" + "float2 size;" + "float2 corner;" + "float2 sizehl;" + "float2 cornerhl;" + "int showhl;" + // shader for displaying head textures + "float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {" + "float backdrop = tex2D(s0, Tex).a;" + "float3 result;" + "if (abs(backdrop - 1.0) < 0.001) {" // (48.0 / 255.0) // 48 - key index color + "result = tex2D(s2, saturate((Tex - corner) / size));" + "} else {" + "result = tex1D(s1, backdrop).bgr;" // get color in palette and swap R <> B + "}" + // blend highlights + "if (showhl) {" + "float4 h = tex2D(s3, saturate((Tex - cornerhl) / sizehl));" + "result = saturate(result + h);" // saturate(result * (1 - h.a) * h.rgb * h.a)" + "}" + "return float4(result, 1);" + "}" + "technique T1" + "{" + "pass p1 { PixelShader = compile ps_2_0 P1(); }" + "}" + + // main shader + "float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {" + "float3 result = tex1D(s1, tex2D(s0, Tex).a);" // get color in palette + "return float4(result.bgr, 1);" // swap R <> B + "}" + "technique T0" + "{" + "pass p0 { PixelShader = compile ps_2_0 P0(); }" + "}"; + +static const char* gpuEffectL8 = + "texture image;" + "texture palette;" + "texture head;" + "texture highlight;" + "sampler s0 = sampler_state { texture=; };" + "sampler s1 = sampler_state { texture=; minFilter=none; magFilter=none; addressU=clamp; addressV=clamp; };" + "sampler s2 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" + "sampler s3 = sampler_state { texture=; minFilter=linear; magFilter=linear; addressU=clamp; addressV=clamp; };" + "float2 size;" + "float2 corner;" + "float2 sizehl;" + "float2 cornerhl;" + "int showhl;" + // shader for displaying head textures + "float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {" + "float backdrop = tex2D(s0, Tex).r;" + "float3 result;" + "if (abs(backdrop - 1.0) < 0.001) {" + "result = tex2D(s2, saturate((Tex - corner) / size));" + "} else {" + "result = tex1D(s1, backdrop).bgr;" + "}" + // blend highlights + "if (showhl) {" + "float4 h = tex2D(s3, saturate((Tex - cornerhl) / sizehl));" + "result = saturate(result + h);" + "}" + "return float4(result, 1);" + "}" + "technique T1" + "{" + "pass p1 { PixelShader = compile ps_2_0 P1(); }" + "}" + + // main shader + "float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {" + "float3 result = tex1D(s1, tex2D(s0, Tex).r);" + "return float4(result.bgr, 1);" + "}" + "technique T0" + "{" + "pass p0 { PixelShader = compile ps_2_0 P0(); }" + "}"; + } diff --git a/sfall/Modules/SpeedPatch.cpp b/sfall/Modules/SpeedPatch.cpp index dc93db78..beffe54d 100644 --- a/sfall/Modules/SpeedPatch.cpp +++ b/sfall/Modules/SpeedPatch.cpp @@ -65,16 +65,16 @@ static bool enabled = true; static bool toggled = false; static bool slideShow = false; -static double multi; +static float multi; static DWORD sfallTickCount = 0; static DWORD lastTickCount; -static double tickCountFraction = 0.0; +static float tickCountFraction = 0.0f; static __int64 startTime; static struct SpeedCfg { int key; - double multiplier; + float multiplier; } *speed = nullptr; static int modKey[2]; @@ -125,7 +125,7 @@ static DWORD __stdcall FakeGetTickCount() { return sfallTickCount; } - double elapsed = (double)(newTickCount - lastTickCount); + float elapsed = static_cast(newTickCount - lastTickCount); lastTickCount = newTickCount; // Multiply the tick count difference by the multiplier @@ -135,13 +135,13 @@ static DWORD __stdcall FakeGetTickCount() { { elapsed *= multi; elapsed += tickCountFraction; - tickCountFraction = modf(elapsed, &elapsed); + tickCountFraction = std::modf(elapsed, &elapsed); if (defaultDelay) SetKeyboardDelay(); } else { SetKeyboardDefaultDelay(); } - sfallTickCount += (DWORD)elapsed; + sfallTickCount += static_cast(elapsed); return sfallTickCount; } @@ -184,7 +184,7 @@ void TimerInit() { _itoa(i, buf, 10); spKey[8] = spMulti[10] = buf[0]; speed[i].key = IniReader::GetConfigInt("Input", spKey, 0); - speed[i].multiplier = IniReader::GetConfigInt("Speed", spMulti, 0) / 100.0; + speed[i].multiplier = IniReader::GetConfigInt("Speed", spMulti, 0) / 100.0f; } } @@ -213,7 +213,7 @@ void SpeedPatch::init() { modKey[1] = 0; } - multi = (double)init / 100.0; + multi = init / 100.0f; toggleKey = IniReader::GetConfigInt("Input", "SpeedToggleKey", 0); getTickCountOffs = (DWORD)&FakeGetTickCount;