From f3c6931f58e5da22ce2a5c97162565bd1cceff7c Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Tue, 2 Jun 2026 22:10:27 +0200 Subject: [PATCH 01/12] string optimizations --- D3D11Engine/D3D7/MyDirectDrawSurface7.cpp | 2 +- D3D11Engine/GothicAPI.cpp | 4 ++-- D3D11Engine/WorldConverter.cpp | 20 ++++++++++++++------ D3D11Engine/zCTexture.h | 23 ++++++++++++++++++++--- D3D11Engine/zSTRING.h | 15 ++++++++++----- 5 files changed, 47 insertions(+), 17 deletions(-) diff --git a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp index e33c93c4..42016291 100644 --- a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp +++ b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp @@ -83,7 +83,7 @@ void MyDirectDrawSurface7::BindToSlot( int slot ) { void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { if ( !GothicTexture ) { GothicTexture = ownedTexture; - TextureName = GothicTexture->GetNameWithoutExt(); + TextureName = GothicTexture->GetNameWithoutExtView(); // Find texture type if ( Toolbox::StringContainsOneOf( TextureName, LEAF_SUBSTR, std::size( LEAF_SUBSTR ) ) ) { diff --git a/D3D11Engine/GothicAPI.cpp b/D3D11Engine/GothicAPI.cpp index 642d4d99..17737b18 100644 --- a/D3D11Engine/GothicAPI.cpp +++ b/D3D11Engine/GothicAPI.cpp @@ -4782,8 +4782,8 @@ MaterialInfo* GothicAPI::GetMaterialInfoFrom( zCTexture* tex ) { MaterialInfos.emplace(tex, std::move(info)); mi = MaterialInfos[tex].get(); if ( tex ) { - mi->LoadFromFile( tex->GetNameWithoutExt() ); - if ( std::string_view{ tex->__GetName().ToChar() } == "NW_MISC_FULLALPHA_01.TGA" ) { + mi->LoadFromFile( tex->GetNameWithoutExtView() ); + if ( tex->GetNameView() == "NW_MISC_FULLALPHA_01.TGA" ) { mi->MaterialType = MaterialInfo::MT_FullAlpha; } } diff --git a/D3D11Engine/WorldConverter.cpp b/D3D11Engine/WorldConverter.cpp index 769ed2fd..61242752 100644 --- a/D3D11Engine/WorldConverter.cpp +++ b/D3D11Engine/WorldConverter.cpp @@ -410,19 +410,27 @@ XRESULT WorldConverter::LoadWorldMeshFromFile( const std::string& file, std::map return XR_SUCCESS; } +static bool findStringIC( const std::string_view strHaystack, const std::string_view strNeedle ) +{ + auto it = std::search( + strHaystack.begin(), strHaystack.end(), + strNeedle.begin(), strNeedle.end(), + []( unsigned char ch1, unsigned char ch2 ) { return std::toupper( ch1 ) == std::toupper( ch2 ); } + ); + return (it != strHaystack.end()); +} + bool AdditionalCheckWaterFall(zCTexture* texture) { if ( !texture ) { return false; } - - std::string textureName = texture->GetName(); - std::transform( textureName.begin(), textureName.end(), textureName.begin(), toupper ); + const std::string_view textureName = texture->GetNameView(); #ifdef BUILD_GOTHIC_2_6_fix - if ( textureName.find( "FALL" ) != std::string::npos && textureName.find( "SURFACE" ) == std::string::npos && textureName.find( "STONE" ) == std::string::npos - && textureName.find( "A0" ) != std::string::npos ) { + if ( findStringIC( textureName, "FALL" ) && !findStringIC( textureName, "SURFACE" ) && !findStringIC( textureName, "STONE" ) + && findStringIC( textureName, "A0" ) ) { #else - if ( textureName.find( "FALL" ) != std::string::npos && (textureName.find( "SURFACE" ) != std::string::npos || textureName.find( "STONE" ) != std::string::npos) ) { + if ( findStringIC( textureName, "FALL" ) && (findStringIC( textureName, "SURFACE" ) || findStringIC( textureName, "STONE" )) ) { #endif // Let's make it work at least with og waterfall foam return true; diff --git a/D3D11Engine/zCTexture.h b/D3D11Engine/zCTexture.h index 18567be3..eb20a600 100644 --- a/D3D11Engine/zCTexture.h +++ b/D3D11Engine/zCTexture.h @@ -46,15 +46,15 @@ class zCTexture { } */ - std::string GetName() { + std::string GetName() const { const zSTRING& str = __GetName(); return std::string( str.ToChar(), static_cast( str.Length() ) ); } - std::string GetNameWithoutExt() { + std::string GetNameWithoutExt() const { std::string n = GetName(); - int p = n.find_last_of( '.' ); + auto p = n.find_last_of( '.' ); if ( p != std::string::npos ) n.resize( p ); @@ -62,6 +62,23 @@ class zCTexture { return n; } + std::string_view GetNameView() const { + const zSTRING& str = __GetName(); + std::string_view n = std::string_view( str.ToChar(), str.Length() ); + return n; + } + + std::string_view GetNameWithoutExtView() const { + std::string_view n = GetNameView(); + + auto p = n.find_last_of( '.' ); + + if ( p != std::string::npos ) + return n.substr( 0, p ); + + return n; + } + MyDirectDrawSurface7* GetSurface() { return *reinterpret_cast(THISPTR_OFFSET( GothicMemoryLocations::zCTexture::Offset_Surface )); } diff --git a/D3D11Engine/zSTRING.h b/D3D11Engine/zSTRING.h index 860caf93..ed288169 100644 --- a/D3D11Engine/zSTRING.h +++ b/D3D11Engine/zSTRING.h @@ -16,14 +16,19 @@ class zSTRING { } const char* ToChar() const { - const char* str = *reinterpret_cast(reinterpret_cast(this) + GothicMemoryLocations::zSTRING::ToChar); - return (str ? str : ""); + return _dataPtr ? _dataPtr : ""; } - int Length() const + size_t Length() const { - return *reinterpret_cast(reinterpret_cast(this) + 0x0C); + return length; } - char data[20]; +private: + void* _vtblString; + void* _unknwn; + //--- + char* _dataPtr; + size_t length; + size_t reserved; }; From e7aab91b88ff6453c0bb826c394e83acbb124512 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Tue, 2 Jun 2026 22:41:51 +0200 Subject: [PATCH 02/12] restructure lookup --- D3D11Engine/WorldConverter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/D3D11Engine/WorldConverter.cpp b/D3D11Engine/WorldConverter.cpp index 61242752..dd8cb41e 100644 --- a/D3D11Engine/WorldConverter.cpp +++ b/D3D11Engine/WorldConverter.cpp @@ -412,7 +412,7 @@ XRESULT WorldConverter::LoadWorldMeshFromFile( const std::string& file, std::map static bool findStringIC( const std::string_view strHaystack, const std::string_view strNeedle ) { - auto it = std::search( + const auto it = std::search( strHaystack.begin(), strHaystack.end(), strNeedle.begin(), strNeedle.end(), []( unsigned char ch1, unsigned char ch2 ) { return std::toupper( ch1 ) == std::toupper( ch2 ); } @@ -427,8 +427,11 @@ bool AdditionalCheckWaterFall(zCTexture* texture) } const std::string_view textureName = texture->GetNameView(); #ifdef BUILD_GOTHIC_2_6_fix - if ( findStringIC( textureName, "FALL" ) && !findStringIC( textureName, "SURFACE" ) && !findStringIC( textureName, "STONE" ) - && findStringIC( textureName, "A0" ) ) { + if ( findStringIC( textureName, "FALL" ) + && findStringIC( textureName, "A0" ) + && !findStringIC( textureName, "SURFACE" ) + && !findStringIC( textureName, "STONE" ) + ) { #else if ( findStringIC( textureName, "FALL" ) && (findStringIC( textureName, "SURFACE" ) || findStringIC( textureName, "STONE" )) ) { #endif From 0976a075d3ddb6a645e8a460e796b0d79f42cd5c Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Tue, 2 Jun 2026 23:34:06 +0200 Subject: [PATCH 03/12] prepare for vdfs --- D3D11Engine/D3D11Engine.vcxproj | 1 + D3D11Engine/D3D11Engine.vcxproj.filters | 47 +++++++--------------- D3D11Engine/D3D11GraphicsEngine.cpp | 4 ++ D3D11Engine/GothicMemoryLocations2_6_fix.h | 15 +++++++ D3D11Engine/zFILE_VDFS.h | 40 ++++++++++++++++++ 5 files changed, 74 insertions(+), 33 deletions(-) create mode 100644 D3D11Engine/zFILE_VDFS.h diff --git a/D3D11Engine/D3D11Engine.vcxproj b/D3D11Engine/D3D11Engine.vcxproj index cdd3dc69..9bab62c9 100644 --- a/D3D11Engine/D3D11Engine.vcxproj +++ b/D3D11Engine/D3D11Engine.vcxproj @@ -1110,6 +1110,7 @@ copy "$(OutDir)$(TargetName).pdb" "$(G1_SYSTEM_PATH)\ddraw.pdb" + diff --git a/D3D11Engine/D3D11Engine.vcxproj.filters b/D3D11Engine/D3D11Engine.vcxproj.filters index cdd93d9f..2dfc0a10 100644 --- a/D3D11Engine/D3D11Engine.vcxproj.filters +++ b/D3D11Engine/D3D11Engine.vcxproj.filters @@ -732,24 +732,6 @@ Engine\D3D11\PFX - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - Engine\D3D11 @@ -856,6 +838,15 @@ Engine\D3D11 + + + + + + + + Engine\GAPI + @@ -1078,21 +1069,6 @@ Engine\D3D11\PFX - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - - - Librarys\ImGuizmo - Engine\D3D11 @@ -1172,6 +1148,11 @@ + + + + + diff --git a/D3D11Engine/D3D11GraphicsEngine.cpp b/D3D11Engine/D3D11GraphicsEngine.cpp index 33814d56..1bc05e28 100644 --- a/D3D11Engine/D3D11GraphicsEngine.cpp +++ b/D3D11Engine/D3D11GraphicsEngine.cpp @@ -55,6 +55,7 @@ #include "zCOption.h" #include "RenderGraph.h" #include "D3D11Upscaling.h" +#include "zFILE_VDFS.h" #ifdef BUILD_SPACER #define IS_SPACER_BUILD true @@ -1415,6 +1416,9 @@ static const char* beginFrameEventName = "Frame"; /** Called when the game wants to render a new frame */ XRESULT D3D11GraphicsEngine::OnBeginFrame() { + + zFILE_VDFS::Create( "_WORK\\DATA\\TEXTURES\\_COMPILED\\AL_D_CELLAR-C.TEX" ); + FrameMarkStart( beginFrameEventName ); auto& rendererState = Engine::GAPI->GetRendererState(); diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix.h b/D3D11Engine/GothicMemoryLocations2_6_fix.h index ff96e813..8b039981 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix.h @@ -719,4 +719,19 @@ struct GothicMemoryLocations { protected: VobTypes() {} }; + + + struct zFILE_VDFS + { + static const unsigned int StructSize = 0x2a24; + + static const unsigned int Constructor2 = 0x00448e20; + static const unsigned int Destructor = 0x00448ed0; + static const unsigned int Exists = 0x00449020; + static const unsigned int Open = 0x00449120; + static const unsigned int Close = 0x004493a0; + static const unsigned int Read = 0x0044abf0; + static const unsigned int Size = 0x00449410; + static const unsigned int zCObjectFactory__CreateZFile = 0x005ab940; + }; }; diff --git a/D3D11Engine/zFILE_VDFS.h b/D3D11Engine/zFILE_VDFS.h new file mode 100644 index 00000000..fa38602a --- /dev/null +++ b/D3D11Engine/zFILE_VDFS.h @@ -0,0 +1,40 @@ +#pragma once +#include "zSTRING.h" + +typedef int zERROR_ID; + +class zFILE_VDFS { +public: + + static zFILE_VDFS* Create( const zSTRING& fileName ) { + auto file = (zFILE_VDFS*)malloc( GothicMemoryLocations::zFILE_VDFS::StructSize ); + if ( file ) { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(file, fileName); + } + return file; + } + + static void Delete( zFILE_VDFS* _this ) { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(_this); + free( _this ); + } + + bool Exists() { + return reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Exists)(this); + } + + zERROR_ID Open( bool writeMode ) { + return reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Open)(this, writeMode); + } + zERROR_ID Close() { + return reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Close)(this); + } + + long Read( void* scr, long bytes ) { + return reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Read)(this, scr, bytes); + } + + long Size() { + return reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Size)(this); + } +}; From f3450475bb03131ee309d2d2a959345b9111fcb1 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 00:29:44 +0200 Subject: [PATCH 04/12] intial run of VDFS support for texture/file loading --- D3D11Engine/D3D11GraphicsEngine.cpp | 4 -- D3D11Engine/D3D11Texture.cpp | 27 ++++++++++++++ D3D11Engine/D3D11Texture.h | 2 + D3D11Engine/D3D7/MyDirectDrawSurface7.cpp | 43 +++++++++++++++++++++- D3D11Engine/GothicAPI.cpp | 1 - D3D11Engine/GothicMemoryLocations2_6_fix.h | 1 + D3D11Engine/zFILE_VDFS.h | 30 ++++++++++----- D3D11Engine/zSTRING.h | 14 ++++++- 8 files changed, 105 insertions(+), 17 deletions(-) diff --git a/D3D11Engine/D3D11GraphicsEngine.cpp b/D3D11Engine/D3D11GraphicsEngine.cpp index 1bc05e28..33814d56 100644 --- a/D3D11Engine/D3D11GraphicsEngine.cpp +++ b/D3D11Engine/D3D11GraphicsEngine.cpp @@ -55,7 +55,6 @@ #include "zCOption.h" #include "RenderGraph.h" #include "D3D11Upscaling.h" -#include "zFILE_VDFS.h" #ifdef BUILD_SPACER #define IS_SPACER_BUILD true @@ -1416,9 +1415,6 @@ static const char* beginFrameEventName = "Frame"; /** Called when the game wants to render a new frame */ XRESULT D3D11GraphicsEngine::OnBeginFrame() { - - zFILE_VDFS::Create( "_WORK\\DATA\\TEXTURES\\_COMPILED\\AL_D_CELLAR-C.TEX" ); - FrameMarkStart( beginFrameEventName ); auto& rendererState = Engine::GAPI->GetRendererState(); diff --git a/D3D11Engine/D3D11Texture.cpp b/D3D11Engine/D3D11Texture.cpp index 9f4c4baf..f7787e90 100644 --- a/D3D11Engine/D3D11Texture.cpp +++ b/D3D11Engine/D3D11Texture.cpp @@ -101,6 +101,33 @@ XRESULT D3D11Texture::Init( const std::string& file ) { return XR_SUCCESS; } +XRESULT D3D11Texture::Init( const uint8_t* data, size_t size, const std::string& debugFileName ) { + HRESULT hr; + D3D11GraphicsEngineBase* engine = reinterpret_cast(Engine::GraphicsEngine); + + //LogInfo() << "Loading Engine-Texture: " << debugFileName; + + Microsoft::WRL::ComPtr res; + LE( CreateDDSTextureFromMemory( engine->GetDevice().Get(), data, size, + reinterpret_cast(res.ReleaseAndGetAddressOf()), ShaderResourceView.GetAddressOf() ) ); + + if ( !ShaderResourceView.Get() || !res.Get() ) + return XR_FAILED; + + D3D11_TEXTURE2D_DESC desc; + res->GetDesc( &desc ); + + Texture = res; + TextureFormat = desc.Format; + + TextureSize.x = desc.Width; + TextureSize.y = desc.Height; + SetDebugName( res.Get(), "D3D11Texture(\"" + debugFileName + "\")->Texture" ); + SetDebugName( ShaderResourceView.Get(), "D3D11Texture(\"" + debugFileName + "\")->ShaderResourceView" ); + + return XR_SUCCESS; +} + /** Updates the Texture-Object */ XRESULT D3D11Texture::UpdateData( void* data, int mip ) { D3D11GraphicsEngineBase* engine = reinterpret_cast(Engine::GraphicsEngine); diff --git a/D3D11Engine/D3D11Texture.h b/D3D11Engine/D3D11Texture.h index 891f8e35..4507f583 100644 --- a/D3D11Engine/D3D11Texture.h +++ b/D3D11Engine/D3D11Texture.h @@ -24,6 +24,8 @@ class D3D11Texture { /** Initializes the texture from a file */ XRESULT Init( const std::string& file ); + XRESULT Init( const uint8_t* data, size_t size, const std::string& debugFileName ); + /** Updates the Texture-Object */ XRESULT UpdateData( void* data, int mip = 0 ); diff --git a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp index 42016291..241e878f 100644 --- a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp +++ b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp @@ -5,6 +5,7 @@ #include "../D3D11Texture.h" #include "../zCTexture.h" #include "../D3D11_Helpers.h" +#include "../zFILE_VDFS.h" #define DebugWriteTex(x) DebugWrite(x) @@ -114,10 +115,50 @@ void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { D3D11Texture* fxMapTexture = nullptr; D3D11Texture* nrmmapTexture = nullptr; + auto file = zFILE_VDFS::Create( (R"(\_WORK\DATA\TEXTURES\REPLACEMENTS\)" + TextureName + "_NORMAL.DDS").c_str() ); + if ( file->Exists() ) { + auto retOpen = file->Open( false ); + if ( retOpen == 0 ) { + auto size = file->Size(); + + std::vector storage( size ); + // assume single op file read. + auto numRead = file->Read( storage.data(), size ); + Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); + if ( XR_SUCCESS != nrmmapTexture->Init( storage.data(), size, TextureName + "_NORMAL.DDS" ) ) { + SAFE_DELETE( nrmmapTexture ); + LogWarn() << "Failed to load normalmap: " << TextureName; + } + + auto retClose = file->Close(); + } + } + file.reset(); + + file = zFILE_VDFS::Create( (R"(\_WORK\DATA\TEXTURES\REPLACEMENTS\)" + TextureName + "_ORM.DDS").c_str() ); + if ( file->Exists() ) { + auto retOpen = file->Open( false ); + if ( retOpen == 0 ) { + auto size = file->Size(); + + std::vector storage( size ); + // assume single op file read. + auto numRead = file->Read( storage.data(), size ); + Engine::GraphicsEngine->CreateTexture( &ormMapTexture ); + if ( XR_SUCCESS != ormMapTexture->Init( storage.data(), size, TextureName + "_ORM.DDS" ) ) { + SAFE_DELETE( ormMapTexture ); + LogWarn() << "Failed to load ORM map: " << TextureName; + } + + auto retClose = file->Close(); + } + } + file.reset(); + // Check for normalmap in our mods folder first, then in the original games int j = 0; std::string replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); - while ( Toolbox::FolderExists( replacementsFolder ) ) { + while ( !nrmmapTexture && Toolbox::FolderExists( replacementsFolder ) ) { std::string normalmap = replacementsFolder + "\\" + TextureName + "_normal.dds"; if ( Toolbox::FileExists( normalmap ) ) { // Create the texture object this is linked with diff --git a/D3D11Engine/GothicAPI.cpp b/D3D11Engine/GothicAPI.cpp index 17737b18..4b21f784 100644 --- a/D3D11Engine/GothicAPI.cpp +++ b/D3D11Engine/GothicAPI.cpp @@ -1835,7 +1835,6 @@ void GothicAPI::OnVisualDeleted( zCVisual* visual ) { if ( str.empty() ) { // Happens when the model has no skeletal-mesh zSTRING mds = zmodel->GetModelName(); str = mds.ToChar(); - mds.Delete(); } auto it = SkeletalMeshVisuals.find( str ); diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix.h b/D3D11Engine/GothicMemoryLocations2_6_fix.h index 8b039981..4c127059 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix.h @@ -732,6 +732,7 @@ struct GothicMemoryLocations { static const unsigned int Close = 0x004493a0; static const unsigned int Read = 0x0044abf0; static const unsigned int Size = 0x00449410; + static const unsigned int SetPath = 0x004455d0; static const unsigned int zCObjectFactory__CreateZFile = 0x005ab940; }; }; diff --git a/D3D11Engine/zFILE_VDFS.h b/D3D11Engine/zFILE_VDFS.h index fa38602a..36d3104d 100644 --- a/D3D11Engine/zFILE_VDFS.h +++ b/D3D11Engine/zFILE_VDFS.h @@ -5,18 +5,28 @@ typedef int zERROR_ID; class zFILE_VDFS { public: - - static zFILE_VDFS* Create( const zSTRING& fileName ) { - auto file = (zFILE_VDFS*)malloc( GothicMemoryLocations::zFILE_VDFS::StructSize ); - if ( file ) { - reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(file, fileName); + zFILE_VDFS() = delete; + ~zFILE_VDFS() = delete; + + // --- Lifetime Management --- + // Returns a managed unique_ptr with a custom deleter to prevent memory leaks + struct Deleter { + void operator()( zFILE_VDFS* file ) const { + if ( file ) { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(file); + std::free( file ); + } } - return file; - } + }; + using Ptr = std::unique_ptr; + + static Ptr Create( const zSTRING& fileName ) { + auto* memory = std::malloc( GothicMemoryLocations::zFILE_VDFS::StructSize ); + if ( !memory ) return nullptr; - static void Delete( zFILE_VDFS* _this ) { - reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(_this); - free( _this ); + auto* file = reinterpret_cast(memory); + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(file, fileName); + return Ptr( file ); } bool Exists() { diff --git a/D3D11Engine/zSTRING.h b/D3D11Engine/zSTRING.h index ed288169..f17c378b 100644 --- a/D3D11Engine/zSTRING.h +++ b/D3D11Engine/zSTRING.h @@ -8,7 +8,19 @@ class zSTRING { reinterpret_cast( GothicMemoryLocations::zSTRING::ConstructorEmptyPtr )( this ); } zSTRING( const char* str ) { - reinterpret_cast( GothicMemoryLocations::zSTRING::ConstructorCharPtr )( this, 0, str ); + reinterpret_cast(GothicMemoryLocations::zSTRING::ConstructorCharPtr)(this, 0, str); + } + + ~zSTRING() { + reinterpret_cast(GothicMemoryLocations::zSTRING::DestructorCharPtr)(this); + } + + static void* operator new(std::size_t count) { + return malloc( std::max( count, sizeof( zSTRING ) ) ); + } + + static void operator delete(void* ptr) { + free(ptr); } void Delete() { From f5054d0ebe3d926a2b8dba67fbf1534fa244a7ab Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:22:32 +0200 Subject: [PATCH 05/12] allocate memory using gothics shw32.dll --- D3D11Engine/D3D11Engine.vcxproj | 1 + D3D11Engine/D3D11Engine.vcxproj.filters | 3 ++ D3D11Engine/GothicMemoryLocations2_6_fix.h | 6 +++ D3D11Engine/ImGuiShim.cpp | 10 +++-- .../include/tracy/public/TracyClient.cpp | 8 +++- D3D11Engine/zAllocator.h | 17 ++++++++ D3D11Engine/zFILE_VDFS.h | 41 +++++++++---------- D3D11Engine/zSTRING.h | 8 ++-- 8 files changed, 63 insertions(+), 31 deletions(-) create mode 100644 D3D11Engine/zAllocator.h diff --git a/D3D11Engine/D3D11Engine.vcxproj b/D3D11Engine/D3D11Engine.vcxproj index 9bab62c9..6e2dbcbe 100644 --- a/D3D11Engine/D3D11Engine.vcxproj +++ b/D3D11Engine/D3D11Engine.vcxproj @@ -1088,6 +1088,7 @@ copy "$(OutDir)$(TargetName).pdb" "$(G1_SYSTEM_PATH)\ddraw.pdb" + diff --git a/D3D11Engine/D3D11Engine.vcxproj.filters b/D3D11Engine/D3D11Engine.vcxproj.filters index 2dfc0a10..8ec7a9d9 100644 --- a/D3D11Engine/D3D11Engine.vcxproj.filters +++ b/D3D11Engine/D3D11Engine.vcxproj.filters @@ -847,6 +847,9 @@ Engine\GAPI + + Engine\GAPI + diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix.h b/D3D11Engine/GothicMemoryLocations2_6_fix.h index 4c127059..59048e58 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix.h @@ -735,4 +735,10 @@ struct GothicMemoryLocations { static const unsigned int SetPath = 0x004455d0; static const unsigned int zCObjectFactory__CreateZFile = 0x005ab940; }; + + struct zAllocator + { + static const unsigned int Malloc = 0x0082e30c; + static const unsigned int Free = 0x0082e308; + }; }; diff --git a/D3D11Engine/ImGuiShim.cpp b/D3D11Engine/ImGuiShim.cpp index ef1a7e5d..78856cf3 100644 --- a/D3D11Engine/ImGuiShim.cpp +++ b/D3D11Engine/ImGuiShim.cpp @@ -143,13 +143,15 @@ void ImGuiShim::RenderLoop() ImGui::GetIO().MouseDrawCursor = GetIsActive() && INT2( ImGui::GetMainViewport()->Size.x, ImGui::GetMainViewport()->Size.y ) != Engine::GraphicsEngine->GetResolution(); - static int beginFrameFn = zCParser::GetParser()->GetIndex( "GDX_IMGUI_BEGINFRAME" ); - static int endFrameFn = zCParser::GetParser()->GetIndex( "GDX_IMGUI_ENDFRAME" ); + static zSTRING GDX_IMGUI_BEGINFRAME = "GDX_IMGUI_BEGINFRAME"; + static zSTRING GDX_IMGUI_ENDFRAME = "GDX_IMGUI_ENDFRAME"; + static int beginFrameFn = zCParser::GetParser()->GetIndex( GDX_IMGUI_BEGINFRAME ); + static int endFrameFn = zCParser::GetParser()->GetIndex( GDX_IMGUI_ENDFRAME ); static int retryFindFuncs = 0; if ( retryFindFuncs > 120 ) { - if ( beginFrameFn == -1 ) { beginFrameFn = zCParser::GetParser()->GetIndex( "GDX_IMGUI_BEGINFRAME" ); } - if ( endFrameFn == -1 ) { endFrameFn = zCParser::GetParser()->GetIndex( "GDX_IMGUI_ENDFRAME" ); } + if ( beginFrameFn == -1 ) { beginFrameFn = zCParser::GetParser()->GetIndex( GDX_IMGUI_BEGINFRAME ); } + if ( endFrameFn == -1 ) { endFrameFn = zCParser::GetParser()->GetIndex( GDX_IMGUI_ENDFRAME ); } retryFindFuncs = 0; } diff --git a/D3D11Engine/include/tracy/public/TracyClient.cpp b/D3D11Engine/include/tracy/public/TracyClient.cpp index 2e58291e..4d4c7b6b 100644 --- a/D3D11Engine/include/tracy/public/TracyClient.cpp +++ b/D3D11Engine/include/tracy/public/TracyClient.cpp @@ -49,14 +49,18 @@ #include +#include "../../../zAllocator.h" + void* operator new(std::size_t count) { - auto ptr = malloc( count ); + auto ptr = zAllocator::zNew( count ); + // auto ptr = malloc( count ); TracyAlloc( ptr, count ); return ptr; } void operator delete(void* ptr) noexcept { TracyFree( ptr ); - free( ptr ); + // free(ptr); + zAllocator::zFree( ptr ); } diff --git a/D3D11Engine/zAllocator.h b/D3D11Engine/zAllocator.h new file mode 100644 index 00000000..5c2263d5 --- /dev/null +++ b/D3D11Engine/zAllocator.h @@ -0,0 +1,17 @@ +#pragma once + +#include "GothicMemoryLocations.h" + +struct zAllocator { + zAllocator() = delete; + ~zAllocator() = delete; + + static void* zNew( size_t size ) { + typedef void* (__cdecl* zMallocFunc)(size_t size); + return (*reinterpret_cast(GothicMemoryLocations::zAllocator::Malloc))(size); + } + static void zFree( void* ptr ) { + typedef void (__cdecl* zFreeFunc)(void* ptr); + return (*reinterpret_cast(GothicMemoryLocations::zAllocator::Free))(ptr); + } +}; diff --git a/D3D11Engine/zFILE_VDFS.h b/D3D11Engine/zFILE_VDFS.h index 36d3104d..30061cd0 100644 --- a/D3D11Engine/zFILE_VDFS.h +++ b/D3D11Engine/zFILE_VDFS.h @@ -1,32 +1,29 @@ #pragma once #include "zSTRING.h" +#include "zAllocator.h" typedef int zERROR_ID; class zFILE_VDFS { public: - zFILE_VDFS() = delete; - ~zFILE_VDFS() = delete; - - // --- Lifetime Management --- - // Returns a managed unique_ptr with a custom deleter to prevent memory leaks - struct Deleter { - void operator()( zFILE_VDFS* file ) const { - if ( file ) { - reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(file); - std::free( file ); - } - } - }; - using Ptr = std::unique_ptr; - - static Ptr Create( const zSTRING& fileName ) { - auto* memory = std::malloc( GothicMemoryLocations::zFILE_VDFS::StructSize ); - if ( !memory ) return nullptr; - - auto* file = reinterpret_cast(memory); - reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(file, fileName); - return Ptr( file ); + + zFILE_VDFS( const zSTRING& fileName ) { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(this, fileName); + } + ~zFILE_VDFS() { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(this); + } + + static std::unique_ptr Create( const zSTRING& fileName ) { + return std::make_unique( fileName ); + } + + static void* operator new(std::size_t count) { + return zAllocator::zNew( std::max( count, GothicMemoryLocations::zFILE_VDFS::StructSize ) ); + } + + static void operator delete(void* ptr) { + zAllocator::zFree( ptr ); } bool Exists() { diff --git a/D3D11Engine/zSTRING.h b/D3D11Engine/zSTRING.h index f17c378b..5a4e90f2 100644 --- a/D3D11Engine/zSTRING.h +++ b/D3D11Engine/zSTRING.h @@ -1,6 +1,7 @@ #pragma once #include "pch.h" #include "GothicMemoryLocations.h" +#include "zAllocator.h" class zSTRING { public: @@ -16,15 +17,16 @@ class zSTRING { } static void* operator new(std::size_t count) { - return malloc( std::max( count, sizeof( zSTRING ) ) ); + return zAllocator::zNew( std::max( count, sizeof( zSTRING ) ) ); } static void operator delete(void* ptr) { - free(ptr); + zAllocator::zFree(ptr); } void Delete() { - reinterpret_cast( GothicMemoryLocations::zSTRING::DestructorCharPtr )( this ); + // no-op, as we have a proper destructor now. + // reinterpret_cast( GothicMemoryLocations::zSTRING::DestructorCharPtr )( this ); } const char* ToChar() const { From 43ad44fba0412e85c895cc6190101f0b37002cd1 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:32:08 +0200 Subject: [PATCH 06/12] allow loading normal map from zFILE_VDFS --- D3D11Engine/D3D7/MyDirectDrawSurface7.cpp | 80 ++++++++++++----------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp index 241e878f..5963fd7a 100644 --- a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp +++ b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp @@ -135,7 +135,7 @@ void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { } file.reset(); - file = zFILE_VDFS::Create( (R"(\_WORK\DATA\TEXTURES\REPLACEMENTS\)" + TextureName + "_ORM.DDS").c_str() ); + file = zFILE_VDFS::Create( (R"(\_WORK\DATA\TEXTURES\REPLACEMENTS\)" + TextureName + "_FX.DDS").c_str() ); if ( file->Exists() ) { auto retOpen = file->Open( false ); if ( retOpen == 0 ) { @@ -144,10 +144,10 @@ void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { std::vector storage( size ); // assume single op file read. auto numRead = file->Read( storage.data(), size ); - Engine::GraphicsEngine->CreateTexture( &ormMapTexture ); - if ( XR_SUCCESS != ormMapTexture->Init( storage.data(), size, TextureName + "_ORM.DDS" ) ) { - SAFE_DELETE( ormMapTexture ); - LogWarn() << "Failed to load ORM map: " << TextureName; + Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); + if ( XR_SUCCESS != fxMapTexture->Init( storage.data(), size, TextureName + "_FX.DDS" ) ) { + SAFE_DELETE( fxMapTexture ); + LogWarn() << "Failed to load FX map: " << TextureName; } auto retClose = file->Close(); @@ -157,54 +157,58 @@ void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { // Check for normalmap in our mods folder first, then in the original games int j = 0; - std::string replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); - while ( !nrmmapTexture && Toolbox::FolderExists( replacementsFolder ) ) { - std::string normalmap = replacementsFolder + "\\" + TextureName + "_normal.dds"; - if ( Toolbox::FileExists( normalmap ) ) { + if ( !nrmmapTexture ) { + std::string replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + while ( !nrmmapTexture && Toolbox::FolderExists( replacementsFolder ) ) { + std::string normalmap = replacementsFolder + "\\" + TextureName + "_normal.dds"; + if ( Toolbox::FileExists( normalmap ) ) { + // Create the texture object this is linked with + Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); + if ( XR_SUCCESS != nrmmapTexture->Init( normalmap ) ) { + SAFE_DELETE( nrmmapTexture ); + LogWarn() << "Failed to load normalmap: " << normalmap; + } + break; // No need to check the other folders + } + j++; + replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + } + std::string normalmap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_normal.dds"; + if ( !nrmmapTexture && Toolbox::FileExists( normalmap ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); if ( XR_SUCCESS != nrmmapTexture->Init( normalmap ) ) { SAFE_DELETE( nrmmapTexture ); LogWarn() << "Failed to load normalmap: " << normalmap; } - break; // No need to check the other folders - } - j++; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); - } - std::string normalmap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_normal.dds"; - if ( !nrmmapTexture && Toolbox::FileExists( normalmap ) ) { - // Create the texture object this is linked with - Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); - if ( XR_SUCCESS != nrmmapTexture->Init( normalmap ) ) { - SAFE_DELETE( nrmmapTexture ); - LogWarn() << "Failed to load normalmap: " << normalmap; } } - j = 0; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); - while ( Toolbox::FolderExists( replacementsFolder ) ) { - std::string fxMap = replacementsFolder + "\\" + TextureName + "_fx.dds"; - if ( Toolbox::FileExists( fxMap ) ) { + if ( !fxMapTexture ) { + j = 0; + replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + while ( !fxMapTexture && Toolbox::FolderExists( replacementsFolder ) ) { + std::string fxMap = replacementsFolder + "\\" + TextureName + "_fx.dds"; + if ( Toolbox::FileExists( fxMap ) ) { + // Create the texture object this is linked with + Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); + if ( XR_SUCCESS != fxMapTexture->Init( fxMap ) ) { + SAFE_DELETE( fxMapTexture ); + LogWarn() << "Failed to load fxMap: " << fxMap; + } + break; // No need to check the other folders + } + j++; + replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + } + std::string fxMap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_fx.dds"; + if ( !fxMapTexture && Toolbox::FileExists( fxMap ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); if ( XR_SUCCESS != fxMapTexture->Init( fxMap ) ) { SAFE_DELETE( fxMapTexture ); LogWarn() << "Failed to load fxMap: " << fxMap; } - break; // No need to check the other folders - } - j++; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); - } - std::string fxMap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_fx.dds"; - if ( !fxMapTexture && Toolbox::FileExists( fxMap ) ) { - // Create the texture object this is linked with - Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); - if ( XR_SUCCESS != fxMapTexture->Init( fxMap ) ) { - SAFE_DELETE( fxMapTexture ); - LogWarn() << "Failed to load fxMap: " << fxMap; } } From ad8586215d3a1b99b0b8121c2dd5199f51af79c4 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 18:39:52 +0200 Subject: [PATCH 07/12] reduce re-allocation in texture data loading --- D3D11Engine/D3D7/MyDirectDrawSurface7.cpp | 50 ++++++++++++++--------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp index 5963fd7a..797da8e0 100644 --- a/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp +++ b/D3D11Engine/D3D7/MyDirectDrawSurface7.cpp @@ -157,57 +157,67 @@ void MyDirectDrawSurface7::LoadAdditionalResources( zCTexture* ownedTexture ) { // Check for normalmap in our mods folder first, then in the original games int j = 0; + thread_local std::string replacementsFolder; + thread_local std::string tmpFilename; if ( !nrmmapTexture ) { - std::string replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + replacementsFolder.resize( 0 ); + replacementsFolder.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(std::to_string(j)); while ( !nrmmapTexture && Toolbox::FolderExists( replacementsFolder ) ) { - std::string normalmap = replacementsFolder + "\\" + TextureName + "_normal.dds"; - if ( Toolbox::FileExists( normalmap ) ) { + tmpFilename.resize( 0 ); + tmpFilename.append(replacementsFolder).append("\\").append(TextureName).append("_normal.dds"); + if ( Toolbox::FileExists( tmpFilename ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); - if ( XR_SUCCESS != nrmmapTexture->Init( normalmap ) ) { + if ( XR_SUCCESS != nrmmapTexture->Init( tmpFilename ) ) { SAFE_DELETE( nrmmapTexture ); - LogWarn() << "Failed to load normalmap: " << normalmap; + LogWarn() << "Failed to load normalmap: " << tmpFilename; } break; // No need to check the other folders } j++; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + replacementsFolder.resize( 0 ); + replacementsFolder.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(std::to_string(j)); } - std::string normalmap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_normal.dds"; - if ( !nrmmapTexture && Toolbox::FileExists( normalmap ) ) { + tmpFilename.resize( 0 ); + tmpFilename.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(Engine::GAPI->GetGameName()).append("\\").append(TextureName).append("_normal.dds"); + if ( !nrmmapTexture && Toolbox::FileExists( tmpFilename ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &nrmmapTexture ); - if ( XR_SUCCESS != nrmmapTexture->Init( normalmap ) ) { + if ( XR_SUCCESS != nrmmapTexture->Init( tmpFilename ) ) { SAFE_DELETE( nrmmapTexture ); - LogWarn() << "Failed to load normalmap: " << normalmap; + LogWarn() << "Failed to load normalmap: " << tmpFilename; } } } if ( !fxMapTexture ) { j = 0; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + replacementsFolder.resize( 0 ); + replacementsFolder.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(std::to_string(j)); while ( !fxMapTexture && Toolbox::FolderExists( replacementsFolder ) ) { - std::string fxMap = replacementsFolder + "\\" + TextureName + "_fx.dds"; - if ( Toolbox::FileExists( fxMap ) ) { + tmpFilename.resize( 0 ); + tmpFilename.append(replacementsFolder).append("\\").append(TextureName).append("_fx.dds"); + if ( Toolbox::FileExists( tmpFilename ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); - if ( XR_SUCCESS != fxMapTexture->Init( fxMap ) ) { + if ( XR_SUCCESS != fxMapTexture->Init( tmpFilename ) ) { SAFE_DELETE( fxMapTexture ); - LogWarn() << "Failed to load fxMap: " << fxMap; + LogWarn() << "Failed to load fxMap: " << tmpFilename; } break; // No need to check the other folders } j++; - replacementsFolder = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + std::to_string( j ); + replacementsFolder.resize( 0 ); + replacementsFolder.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(std::to_string(j)); } - std::string fxMap = "system\\GD3D11\\textures\\replacements\\Normalmaps_" + Engine::GAPI->GetGameName() + "\\" + TextureName + "_fx.dds"; - if ( !fxMapTexture && Toolbox::FileExists( fxMap ) ) { + tmpFilename.resize( 0 ); + tmpFilename.append("system\\GD3D11\\textures\\replacements\\Normalmaps_").append(Engine::GAPI->GetGameName()).append("\\").append(TextureName).append("_fx.dds"); + if ( !fxMapTexture && Toolbox::FileExists( tmpFilename ) ) { // Create the texture object this is linked with Engine::GraphicsEngine->CreateTexture( &fxMapTexture ); - if ( XR_SUCCESS != fxMapTexture->Init( fxMap ) ) { + if ( XR_SUCCESS != fxMapTexture->Init( tmpFilename ) ) { SAFE_DELETE( fxMapTexture ); - LogWarn() << "Failed to load fxMap: " << fxMap; + LogWarn() << "Failed to load fxMap: " << tmpFilename; } } } From 0ef2a3ad15acacc6d67fcd86447c92c4c813c3f8 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:04:49 +0200 Subject: [PATCH 08/12] load rain/snowflakes from VDFS/filesystem with fallback to old system directory --- D3D11Engine/D3D11Effect.cpp | 42 ++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/D3D11Engine/D3D11Effect.cpp b/D3D11Engine/D3D11Effect.cpp index 66e7a427..07613514 100644 --- a/D3D11Engine/D3D11Effect.cpp +++ b/D3D11Engine/D3D11Effect.cpp @@ -17,6 +17,7 @@ // TODO: Remove this! #include "D3D11GraphicsEngine.h" #include "oCGame.h" +#include "zFILE_VDFS.h" constexpr float snowSpeedFactor = 0.15f; @@ -441,12 +442,22 @@ XRESULT D3D11Effect::LoadRainResources() { D3D11GraphicsEngineBase* e = reinterpret_cast(Engine::GraphicsEngine); + std::string path; + path.resize( MAX_PATH ); + path.resize(GetModuleFileNameA( nullptr, path.data(), path.size()-1 )); + + std::filesystem::path basePath = std::filesystem::path( path ).parent_path() / "GD3D11" / "Textures"; + if ( !RainTextureArray.Get() ) { HRESULT hr = S_OK; // Load textures... LogInfo() << "Loading rain-drop textures"; ZoneScopedN( "LoadRainTextures" ); - LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), "system\\GD3D11\\Textures\\Raindrops\\cv0_vPositive_", 370, &RainTextureArray, &RainTextureArraySRV ) ); + LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), "\\_work\\Data\\Textures\\GD3D11\\Raindrops\\cv0_vPositive_", 370, &RainTextureArray, &RainTextureArraySRV ) ); + if (!SUCCEEDED(hr)) { + // try old file paths + LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), (basePath / "Raindrops"/"cv0_vPositive_").string().c_str(), 370, &RainTextureArray, &RainTextureArraySRV ) ); + } } if ( !SnowTextureArray.Get() ) { @@ -454,7 +465,10 @@ XRESULT D3D11Effect::LoadRainResources() // Load textures... LogInfo() << "Loading snow flake textures"; ZoneScopedN( "LoadSnowTextures" ); - LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), "system\\GD3D11\\Textures\\Snowflakes\\Snow_", 256, &SnowTextureArray, &SnowTextureArraySRV ) ); + LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), "\\_work\\Data\\Textures\\GD3D11\\Snowflakes\\Snow_", 256, &SnowTextureArray, &SnowTextureArraySRV ) ); + if (!SUCCEEDED(hr)) { + LE( LoadTextureArray( e->GetDevice().Get(), e->GetContext().Get(), (basePath / "Snowflakes"/"Snow_").string().c_str(), 256, &SnowTextureArray, &SnowTextureArraySRV ) ); + } } if ( !RainShadowmap.get() ) { @@ -625,11 +639,33 @@ HRESULT LoadTextureArray( Microsoft::WRL::ComPtr pd3dDevice, Micr // CHAR szTextureName[MAX_PATH]; CHAR str[MAX_PATH]; + + std::vector storage{}; for ( int i = 0; i < iNumTextures; i++ ) { sprintf( str, "%s%.4d.dds", sTexturePrefix, i ); + auto file = zFILE_VDFS::Create( str ); + if ( !file->Exists() ) { + LogError() << "File does not exist: " << str; + return E_FAIL; + } + auto retOpen = file->Open( false ); + if ( retOpen != 0 ) { + LogError() << "Failed to open filepath: " << str; + return E_FAIL; + } + auto size = file->Size(); + + if ( storage.size() < size ) { + storage.resize( size*2 ); + } + // assume single op file read. + auto numRead = file->Read( storage.data(), size ); + auto retClose = file->Close(); + + Microsoft::WRL::ComPtr pRes; - LE( CreateDDSTextureFromFileEx( pd3dDevice.Get(), Toolbox::ToWideChar( str ).c_str(), 0, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_WRITE, 0, DDS_LOADER_DEFAULT, pRes.GetAddressOf(), nullptr ) ); + LE( CreateDDSTextureFromMemoryEx( pd3dDevice.Get(), storage.data(), size, 0, D3D11_USAGE_STAGING, 0, D3D11_CPU_ACCESS_WRITE, 0, DDS_LOADER_DEFAULT, pRes.GetAddressOf(), nullptr)); if ( pRes.Get() ) { Microsoft::WRL::ComPtr pTemp; pRes.As( &pTemp ); From dae61be8ef18ce666b9879d6501b90834e441ae0 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:28:20 +0200 Subject: [PATCH 09/12] memory locations for G1 --- D3D11Engine/GothicMemoryLocations1_08k.h | 23 +++++++++++++++++++ D3D11Engine/GothicMemoryLocations1_12f.h | 21 +++++++++++++++++ D3D11Engine/GothicMemoryLocations2_6_fix.h | 1 + .../GothicMemoryLocations2_6_fix_Spacer.h | 22 ++++++++++++++++++ D3D11Engine/zAllocator.h | 11 ++++++++- 5 files changed, 77 insertions(+), 1 deletion(-) diff --git a/D3D11Engine/GothicMemoryLocations1_08k.h b/D3D11Engine/GothicMemoryLocations1_08k.h index bdc67dec..7c400f0f 100644 --- a/D3D11Engine/GothicMemoryLocations1_08k.h +++ b/D3D11Engine/GothicMemoryLocations1_08k.h @@ -659,4 +659,27 @@ struct GothicMemoryLocations { protected: VobTypes() {} }; + + + struct zFILE_VDFS + { + static const unsigned int StructSize = 0x2a24; + + static const unsigned int Constructor2 = 0x004468c0; + static const unsigned int Destructor = 0x00444d90; + static const unsigned int Exists = 0x00444f90; + static const unsigned int Open = 0x00445090; + static const unsigned int Close = 0x00445310; + static const unsigned int Read = 0x004468c0; + static const unsigned int Size = 0x00445380; + static const unsigned int SetPath = 0x00441670; + static const unsigned int zCObjectFactory__CreateZFile = 0x0058bd60; + }; + +#define zALLOCATOR_SUPPORTED + struct zAllocator + { + static const unsigned int Malloc = 0x007d02f8; + static const unsigned int Free = 0x007d02ec; + }; }; diff --git a/D3D11Engine/GothicMemoryLocations1_12f.h b/D3D11Engine/GothicMemoryLocations1_12f.h index c7428b2a..488be9f1 100644 --- a/D3D11Engine/GothicMemoryLocations1_12f.h +++ b/D3D11Engine/GothicMemoryLocations1_12f.h @@ -568,4 +568,25 @@ struct GothicMemoryLocations { protected: VobTypes() {} }; + + struct zFILE_VDFS + { + static const unsigned int StructSize = 0x2a24; + + static const unsigned int Constructor2 = 0; + static const unsigned int Destructor = 0; + static const unsigned int Exists = 0; + static const unsigned int Open = 0; + static const unsigned int Close = 0; + static const unsigned int Read = 0; + static const unsigned int Size = 0; + static const unsigned int SetPath = 0; + static const unsigned int zCObjectFactory__CreateZFile = 0; + }; + + struct zAllocator + { + static const unsigned int Malloc = 0; + static const unsigned int Free = 0; + }; }; diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix.h b/D3D11Engine/GothicMemoryLocations2_6_fix.h index 59048e58..ad2d16bd 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix.h @@ -736,6 +736,7 @@ struct GothicMemoryLocations { static const unsigned int zCObjectFactory__CreateZFile = 0x005ab940; }; +#define zALLOCATOR_SUPPORTED struct zAllocator { static const unsigned int Malloc = 0x0082e30c; diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix_Spacer.h b/D3D11Engine/GothicMemoryLocations2_6_fix_Spacer.h index bbf67f85..8767cd5f 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix_Spacer.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix_Spacer.h @@ -475,4 +475,26 @@ struct GothicMemoryLocations { struct oCItemContainer { static const unsigned int s_Container_Draw = 0; }; + + + struct zFILE_VDFS + { + static const unsigned int StructSize = 0x2a24; + + static const unsigned int Constructor2 = 0; + static const unsigned int Destructor = 0; + static const unsigned int Exists = 0; + static const unsigned int Open = 0; + static const unsigned int Close = 0; + static const unsigned int Read = 0; + static const unsigned int Size = 0; + static const unsigned int SetPath = 0; + static const unsigned int zCObjectFactory__CreateZFile = 0; + }; + + struct zAllocator + { + static const unsigned int Malloc = 0; + static const unsigned int Free = 0; + }; }; diff --git a/D3D11Engine/zAllocator.h b/D3D11Engine/zAllocator.h index 5c2263d5..33a72644 100644 --- a/D3D11Engine/zAllocator.h +++ b/D3D11Engine/zAllocator.h @@ -1,5 +1,6 @@ #pragma once +#include #include "GothicMemoryLocations.h" struct zAllocator { @@ -7,11 +8,19 @@ struct zAllocator { ~zAllocator() = delete; static void* zNew( size_t size ) { +#ifdef zALLOCATOR_SUPPORTED typedef void* (__cdecl* zMallocFunc)(size_t size); return (*reinterpret_cast(GothicMemoryLocations::zAllocator::Malloc))(size); +#else + return std::malloc(size); +#endif } static void zFree( void* ptr ) { +#ifdef zALLOCATOR_SUPPORTED typedef void (__cdecl* zFreeFunc)(void* ptr); - return (*reinterpret_cast(GothicMemoryLocations::zAllocator::Free))(ptr); + (*reinterpret_cast(GothicMemoryLocations::zAllocator::Free))(ptr); +#else + std::free(ptr); +#endif } }; From 23872ff4c0f8e4b21a49a90cf554b3118e0645b8 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:37:17 +0200 Subject: [PATCH 10/12] use actual _malloc and _free locations --- D3D11Engine/GothicMemoryLocations1_08k.h | 8 ++++---- D3D11Engine/GothicMemoryLocations2_6_fix.h | 4 ++-- D3D11Engine/zAllocator.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/D3D11Engine/GothicMemoryLocations1_08k.h b/D3D11Engine/GothicMemoryLocations1_08k.h index 7c400f0f..935abc14 100644 --- a/D3D11Engine/GothicMemoryLocations1_08k.h +++ b/D3D11Engine/GothicMemoryLocations1_08k.h @@ -665,8 +665,8 @@ struct GothicMemoryLocations { { static const unsigned int StructSize = 0x2a24; - static const unsigned int Constructor2 = 0x004468c0; - static const unsigned int Destructor = 0x00444d90; + static const unsigned int Constructor2 = 0x00444d90; + static const unsigned int Destructor = 0x00444e40; static const unsigned int Exists = 0x00444f90; static const unsigned int Open = 0x00445090; static const unsigned int Close = 0x00445310; @@ -679,7 +679,7 @@ struct GothicMemoryLocations { #define zALLOCATOR_SUPPORTED struct zAllocator { - static const unsigned int Malloc = 0x007d02f8; - static const unsigned int Free = 0x007d02ec; + static const unsigned int Malloc = 0x0075ad60; + static const unsigned int Free = 0x0075ad6f; }; }; diff --git a/D3D11Engine/GothicMemoryLocations2_6_fix.h b/D3D11Engine/GothicMemoryLocations2_6_fix.h index ad2d16bd..b4396f03 100644 --- a/D3D11Engine/GothicMemoryLocations2_6_fix.h +++ b/D3D11Engine/GothicMemoryLocations2_6_fix.h @@ -739,7 +739,7 @@ struct GothicMemoryLocations { #define zALLOCATOR_SUPPORTED struct zAllocator { - static const unsigned int Malloc = 0x0082e30c; - static const unsigned int Free = 0x0082e308; + static const unsigned int Malloc = 0x007b4460; + static const unsigned int Free = 0x007b446f; }; }; diff --git a/D3D11Engine/zAllocator.h b/D3D11Engine/zAllocator.h index 33a72644..1d1fcad5 100644 --- a/D3D11Engine/zAllocator.h +++ b/D3D11Engine/zAllocator.h @@ -10,7 +10,7 @@ struct zAllocator { static void* zNew( size_t size ) { #ifdef zALLOCATOR_SUPPORTED typedef void* (__cdecl* zMallocFunc)(size_t size); - return (*reinterpret_cast(GothicMemoryLocations::zAllocator::Malloc))(size); + return reinterpret_cast(GothicMemoryLocations::zAllocator::Malloc)(size); #else return std::malloc(size); #endif @@ -18,7 +18,7 @@ struct zAllocator { static void zFree( void* ptr ) { #ifdef zALLOCATOR_SUPPORTED typedef void (__cdecl* zFreeFunc)(void* ptr); - (*reinterpret_cast(GothicMemoryLocations::zAllocator::Free))(ptr); + reinterpret_cast(GothicMemoryLocations::zAllocator::Free)(ptr); #else std::free(ptr); #endif From 06c9f69e5d6c064df1378f6ac1ac43ff0bcbefff Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 19:45:00 +0200 Subject: [PATCH 11/12] fix default materialinfo buffers --- D3D11Engine/D3D11GraphicsEngine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/D3D11Engine/D3D11GraphicsEngine.cpp b/D3D11Engine/D3D11GraphicsEngine.cpp index 33814d56..e1198072 100644 --- a/D3D11Engine/D3D11GraphicsEngine.cpp +++ b/D3D11Engine/D3D11GraphicsEngine.cpp @@ -6730,7 +6730,7 @@ XRESULT D3D11GraphicsEngine::DrawVOBsInstanced() { // Use default material info for now MaterialInfo defInfo = {}; ActivePS->GetBuffer( "MI_MaterialInfo" ) - .Update( &defInfo ) + .Update( &defInfo.buffer ) .Bind(); XMMATRIX view = Engine::GAPI->GetViewMatrixXM(); @@ -7439,9 +7439,9 @@ XRESULT D3D11GraphicsEngine::DrawPolyStrips( bool noTextures ) { .Bind(); // Use default material info for now - MaterialInfo defInfo; + MaterialInfo defInfo{}; ActivePS->GetBuffer( "MI_MaterialInfo" ) - .Update( &defInfo ) + .Update( &defInfo.buffer ) .Bind(); auto vsBufMPI = ActiveVS->GetBuffer( "Matrices_PerInstances" ); From 6722a4701231bd66167dc4e32c7ff2f2ca000961 Mon Sep 17 00:00:00 2001 From: kirides <13602143+kirides@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:17:26 +0200 Subject: [PATCH 12/12] ensure `zFILE_VDFS` is never allocated on stack --- D3D11Engine/zFILE_VDFS.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/D3D11Engine/zFILE_VDFS.h b/D3D11Engine/zFILE_VDFS.h index 30061cd0..a1a776f6 100644 --- a/D3D11Engine/zFILE_VDFS.h +++ b/D3D11Engine/zFILE_VDFS.h @@ -5,17 +5,30 @@ typedef int zERROR_ID; class zFILE_VDFS { +private: + ~zFILE_VDFS() { + reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(this); + } public: - zFILE_VDFS( const zSTRING& fileName ) { reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Constructor2)(this, fileName); } - ~zFILE_VDFS() { - reinterpret_cast(GothicMemoryLocations::zFILE_VDFS::Destructor)(this); - } - static std::unique_ptr Create( const zSTRING& fileName ) { - return std::make_unique( fileName ); + struct Deleter { + void operator()( zFILE_VDFS* file ) const { + if ( file ) { + delete file; + } + } + }; + + using Ptr = std::unique_ptr; + + static Ptr Create( const zSTRING& fileName ) { + + auto ptr = new zFILE_VDFS( fileName ); + + return Ptr( ptr ); } static void* operator new(std::size_t count) {