From b37d1312b268abd20d2cffaf0893cbba6fe99b20 Mon Sep 17 00:00:00 2001 From: andon Date: Sun, 5 Feb 2017 11:12:17 -0500 Subject: [PATCH] Advanced Texture Modding --- include/DLL_VERSION.H | 6 +- include/config.h | 1 + include/textures.h | 9 + src/{tbt => ImGui}/control_panel.cpp | 168 +++-------------- src/ImGui/mod_tools.cpp | 264 +++++++++++++++++++++++++++ src/config.cpp | 13 ++ src/textures.cpp | 81 +++++++- tbf.vcxproj | 3 +- tbf.vcxproj.filters | 9 +- version.ini | Bin 10236 -> 9744 bytes 10 files changed, 398 insertions(+), 156 deletions(-) rename src/{tbt => ImGui}/control_panel.cpp (82%) create mode 100644 src/ImGui/mod_tools.cpp diff --git a/include/DLL_VERSION.H b/include/DLL_VERSION.H index 1e5f58c..a346c0e 100644 --- a/include/DLL_VERSION.H +++ b/include/DLL_VERSION.H @@ -2,9 +2,9 @@ #define TBF_MAJOR 0 -#define TBF_MINOR 7 -#define TBF_BUILD 3 -#define TBF_REV 1 +#define TBF_MINOR 8 +#define TBF_BUILD 0 +#define TBF_REV 0 diff --git a/include/config.h b/include/config.h index 1ae2032..d3dcc6d 100644 --- a/include/config.h +++ b/include/config.h @@ -70,6 +70,7 @@ struct tbf_config_t struct { bool dump = false; + bool on_demand_dump = false; bool remaster = true; bool cache = true; bool uncompressed = false; diff --git a/include/textures.h b/include/textures.h index 8584670..c0be9d9 100644 --- a/include/textures.h +++ b/include/textures.h @@ -502,5 +502,14 @@ typedef HRESULT (STDMETHODCALLTYPE *SetDepthStencilSurface_pfn)( _In_ IDirect3DSurface9 *pNewZStencil ); +HRESULT +TBF_DumpTexture (D3DFORMAT fmt, uint32_t checksum, IDirect3DTexture9* pTex); + +bool +TBF_IsTextureDumped (uint32_t checksum); + +bool +TBF_DeleteDumpedTexture (D3DFORMAT fmt, uint32_t checksum); + #endif /* __TBFIX__TEXTURES_H__ */ \ No newline at end of file diff --git a/src/tbt/control_panel.cpp b/src/ImGui/control_panel.cpp similarity index 82% rename from src/tbt/control_panel.cpp rename to src/ImGui/control_panel.cpp index cf4cac5..0908dc6 100644 --- a/src/tbt/control_panel.cpp +++ b/src/ImGui/control_panel.cpp @@ -29,9 +29,10 @@ bool SK_ImGui_ControlPanel (void); -bool show_config = true; -bool show_special_k_cfg = false; -bool show_test_window = false; +bool show_config = true; +bool show_special_k_cfg = false; +bool show_test_window = false; +bool show_texture_mod_dlg = false; ImVec4 clear_col = ImColor (114, 144, 154); @@ -77,7 +78,11 @@ TBFix_ToggleConfigUI (void) { DWORD dwPos = GetMessagePos (); - SendMessage (tbf::RenderFix::hWndDevice, WM_MOUSEMOVE, 0x00, dwPos); + ImGuiIO& io = + ImGui::GetIO (); + + if (! io.WantCaptureMouse) + SendMessage (tbf::RenderFix::hWndDevice, WM_MOUSEMOVE, 0x00, dwPos); SK_ImGui_Toggle_Original (); @@ -100,11 +105,15 @@ TBFix_ToggleConfigUI (void) TBFix_ReleaseCursor (); } - SendMessage (tbf::RenderFix::hWndDevice, WM_MOUSEMOVE, 0x00, dwPos); + if (! io.WantCaptureMouse) + SendMessage (tbf::RenderFix::hWndDevice, WM_MOUSEMOVE, 0x00, dwPos); TBF_SaveConfig (); } +extern +bool +TBFix_TextureModDlg (void); void TBFix_GamepadConfigDlg (void) @@ -185,7 +194,7 @@ void ImGui_ImplDX9_NewFrame (void); -void +bool TBFix_DrawConfigUI (void) { static bool need_restart = false; @@ -519,144 +528,10 @@ TBFix_DrawConfigUI (void) ImGui::TreePop ( ); } - if (ImGui::CollapsingHeader ("Modding")) - { - ImGui::TreePush (""); - if (ImGui::Checkbox ("Dump Textures (TBFix_Res\\dump\\textures\\\\*.dds)", &config.textures.dump)) tbf::RenderFix::need_reset.graphics = true; - - if (ImGui::IsItemHovered ()) - { - ImGui::BeginTooltip (); - ImGui::Text ("Enabling this will cause the game to run slower and waste disk space, only enable if you know what you are doing."); - ImGui::EndTooltip (); - } - - ImGui::BeginChild ("ModDescription", ImVec2 (750, 325), true); - ImGui::TextColored (ImVec4 (0.9f, 0.7f, 0.5f, 1.0f), "Texture Modding Overview"); ImGui::SameLine (); - ImGui::Text (" (Documentation Pending)"); - - ImGui::Separator (); - - ImGui::TextWrapped ("\nReplacement textures go in (TBFix_Res\\inject\\textures\\{blocking|streaming}\\.dds)\n\n"); - - ImGui::TreePush (""); - ImGui::BulletText ("Blocking textures have a high performance penalty, but zero chance of visible pop-in."); - ImGui::BulletText ("Streaming textures will replace the game's original texture whenever Disk/CPU loads finish."); - ImGui::TreePush (""); - ImGui::PushStyleColor (ImGuiCol_Text, ImVec4 (0.6f, 0.9f, 0.2f, 1.0f)); - ImGui::BulletText ("Use streaming whenever possible or performance will bite you in the ass."); - ImGui::PopStyleColor (); - ImGui::TreePop ( ); - ImGui::TreePop (); - - ImGui::TextWrapped ("\n\nLoading modified textures from separate files is inefficient; entire groups of textures may also be packaged into \".7z\" files (See TBFix_Res\\inject\\00_License.7z as an example, and use low/no compression ratio or you will kill the game's performance).\n"); - - ImGui::Separator (); - - ImGui::PushStyleColor (ImGuiCol_Text, ImVec4 (0.9f, 0.6f, 0.3f, 1.0f)); - ImGui::TextWrapped ( "\n\nA more detailed synopsis will follow in future versions, for now please refer to the GitHub release notes for Tales of Symphonia " - "\"Fix\" v 0.9.0 for a thorough description on authoring texture mods.\n\n" ); - ImGui::PopStyleColor (); - - ImGui::Separator (); - - ImGui::Bullet (); ImGui::SameLine (); - ImGui::TextWrapped ( "\nIf texture mods are enabled, you can click on the Injected and Base buttons on the texture cache " - "summary pannel to compare modified and unmodified." ); - ImGui::EndChild (); - - ImGui::SameLine (); - - ImGui::BeginChild ("DebugTexture", ImVec2 (300, 325)); - - static std::vector list_contents; - static bool list_dirty = false; - static int sel = 0; - - extern std::vector textures_used_last_dump; - extern uint32_t tex_dbg_idx; - extern uint32_t debug_tex_id; - - if (list_dirty) - { - list_contents.clear (); - sel = tex_dbg_idx; - - for ( auto it : textures_used_last_dump ) - { - char szDesc [16] = { }; - - sprintf (szDesc, "%08x", it); - - list_contents.push_back (szDesc); - } - } - - if (ImGui::Button ("Refresh Textures")) - { - SK_ICommandProcessor& command = - *SK_GetCommandProcessor (); - - command.ProcessCommandLine ("Textures.Trace true"); - - tbf::RenderFix::tex_mgr.updateOSD (); - - list_dirty = true; - } - - if (ImGui::IsItemHovered ()) ImGui::SetTooltip ("Refreshes the set of texture checksums used in the last frame drawn."); - - ImGui::SameLine (); - - if (ImGui::Button ("Clear Debug")) - { - sel = -1; - debug_tex_id = 0; - textures_used_last_dump.clear (); - } - - if (ImGui::IsItemHovered ()) ImGui::SetTooltip ("Exits texture debug mode."); - - //if (ImGui::Button ("Dump Selected")) - //{ - //} - - if ( ImGui::ListBox ( - "", &sel, - [](void *data, int idx, const char **out_data) -> - bool { - *out_data = list_contents [idx].c_str (); - - return true; - }, - nullptr, - textures_used_last_dump.size (), - textures_used_last_dump.size () ) - ) - { - if ((int32_t)tex_dbg_idx < 0 || (! textures_used_last_dump.size ())) { - tex_dbg_idx = -1; - debug_tex_id = 0; - } else { - tex_dbg_idx = sel; - - debug_tex_id = textures_used_last_dump [sel]; - } - } - - if (ImGui::IsItemHovered ()) - { - ImGui::BeginTooltip (); - ImGui::TextColored (ImVec4 (0.7f, 0.9f, 0.3f, 1.0f), "The \"debug\" texture will appear black to make identifying textures to modify easier."); - ImGui::Separator (); - ImGui::BulletText ("Press Ctrl + Shift + [ to select the previous texture from this list"); - ImGui::BulletText ("Press Ctrl + Shift + ] to select the next texture from this list"); - ImGui::EndTooltip (); - } - - ImGui::EndChild (); - ImGui::TreePop (); + if (ImGui::Button ("Texture Modding Tools")) { + show_texture_mod_dlg = (! show_texture_mod_dlg); } + ImGui::TreePop (); } @@ -857,6 +732,11 @@ TBFix_DrawConfigUI (void) if (show_special_k_cfg) show_special_k_cfg = SK_ImGui_ControlPanel (); + if (show_texture_mod_dlg) + { + show_texture_mod_dlg = TBFix_TextureModDlg (); + } + if ( SUCCEEDED ( tbf::RenderFix::pDevice->BeginScene () ) @@ -870,6 +750,8 @@ TBFix_DrawConfigUI (void) { TBFix_ToggleConfigUI (); } + + return show_config; } diff --git a/src/ImGui/mod_tools.cpp b/src/ImGui/mod_tools.cpp new file mode 100644 index 0000000..3aad79a --- /dev/null +++ b/src/ImGui/mod_tools.cpp @@ -0,0 +1,264 @@ +#define NOMINMAX + +#include "DLL_VERSION.H" +#include "imgui\imgui.h" + +#include +#include +#include + +#include "config.h" +#include "command.h" +#include "render.h" +#include "textures.h" + +bool +TBFix_TextureModDlg (void) +{ + bool show_dlg = true; + + ImGui::Begin ( "Tales Engine Texture Mod Toolkit (v " TBF_VERSION_STR_A ")", + &show_dlg, + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_ShowBorders ); + + ImGui::PushItemWidth (ImGui::GetWindowWidth () * 0.666f); + + if (ImGui::CollapsingHeader ("Preliminary Documentation", ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::BeginChild ("ModDescription", ImVec2 (750, 325), true); + ImGui::TextColored (ImVec4 (0.9f, 0.7f, 0.5f, 1.0f), "Texture Modding Overview"); ImGui::SameLine (); + ImGui::Text (" (Full Writeup Pending)"); + + ImGui::Separator (); + + ImGui::TextWrapped ("\nReplacement textures go in (TBFix_Res\\inject\\textures\\{blocking|streaming}\\.dds)\n\n"); + + ImGui::TreePush (""); + ImGui::BulletText ("Blocking textures have a high performance penalty, but zero chance of visible pop-in."); + ImGui::BulletText ("Streaming textures will replace the game's original texture whenever Disk/CPU loads finish."); + ImGui::TreePush (""); + ImGui::PushStyleColor (ImGuiCol_Text, ImVec4 (0.6f, 0.9f, 0.2f, 1.0f)); + ImGui::BulletText ("Use streaming whenever possible or performance will bite you in the ass."); + ImGui::PopStyleColor (); + ImGui::TreePop ( ); + ImGui::TreePop (); + + ImGui::TextWrapped ("\n\nLoading modified textures from separate files is inefficient; entire groups of textures may also be packaged into \".7z\" files (See TBFix_Res\\inject\\00_License.7z as an example, and use low/no compression ratio or you will kill the game's performance).\n"); + + ImGui::Separator (); + + ImGui::PushStyleColor (ImGuiCol_Text, ImVec4 (0.9f, 0.6f, 0.3f, 1.0f)); + ImGui::TextWrapped ( "\n\nA more detailed synopsis will follow in future versions, for now please refer to the GitHub release notes for Tales of Symphonia " + "\"Fix\" v 0.9.0 for a thorough description on authoring texture mods.\n\n" ); + ImGui::PopStyleColor (); + + ImGui::Separator (); + + ImGui::Bullet (); ImGui::SameLine (); + ImGui::TextWrapped ( "If texture mods are enabled, you can click on the Injected and Base buttons on the texture cache " + "summary pannel to compare modified and unmodified." ); + ImGui::EndChild (); + } + + if (ImGui::CollapsingHeader ("Texture Selection", ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_DefaultOpen)) + { + static LONG last_ht = 256L; + static LONG last_width = 256L; + + static std::vector list_contents; + static bool list_dirty = false; + static int sel = 0; + + extern std::vector textures_used_last_dump; + extern uint32_t tex_dbg_idx; + extern uint32_t debug_tex_id; + + ImGui::TreePush (""); + if (ImGui::Button ("Refresh Textures")) + { + SK_ICommandProcessor& command = + *SK_GetCommandProcessor (); + + command.ProcessCommandLine ("Textures.Trace true"); + + tbf::RenderFix::tex_mgr.updateOSD (); + + list_dirty = true; + } + + if (ImGui::IsItemHovered ()) ImGui::SetTooltip ("Refreshes the set of texture checksums used in the last frame drawn."); + + ImGui::SameLine (); + + if (ImGui::Button ("Clear Debug")) + { + sel = -1; + debug_tex_id = 0; + textures_used_last_dump.clear (); + last_ht = 0; + last_width = 0; + } + + if (ImGui::IsItemHovered ()) ImGui::SetTooltip ("Exits texture debug mode."); + + ImGui::SameLine (); + + if (ImGui::Checkbox ("Enable On-Demand Texture Dumping", &config.textures.on_demand_dump)) tbf::RenderFix::need_reset.graphics = true; + + if (ImGui::IsItemHovered ()) + { + ImGui::BeginTooltip (); + ImGui::TextColored (ImVec4 (0.9f, 0.7f, 0.3f, 1.f), "Enable dumping DXT compressed textures from VRAM."); + ImGui::Separator (); + ImGui::Text ("Drivers may not be able to manage texture memory as efficiently, and you should turn this option off when not modifying textures.\n\n"); + ImGui::BulletText ("If this is your first time enabling this feature, the dump button will not work until you reload all textures in-game."); + ImGui::EndTooltip (); + } + + ImGui::Separator (); + + ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 2.0f); + ImGui::BeginChild ("DebugTextures", ImVec2 (100, std::max (last_ht + 128, 18L * (LONG)textures_used_last_dump.size ()))); + + if (list_dirty) + { + list_contents.clear (); + sel = tex_dbg_idx; + + for ( auto it : textures_used_last_dump ) + { + char szDesc [16] = { }; + + sprintf (szDesc, "%08x", it); + + list_contents.push_back (szDesc); + } + } + + if ( ImGui::ListBox ( + "", &sel, + [](void *data, int idx, const char **out_data) -> + bool { + *out_data = list_contents [idx].c_str (); + + return true; + }, + nullptr, + textures_used_last_dump.size (), + textures_used_last_dump.size () ) + ) + { + if ((int32_t)tex_dbg_idx < 0 || (! textures_used_last_dump.size ())) { + tex_dbg_idx = -1; + debug_tex_id = 0; + } else { + tex_dbg_idx = sel; + + debug_tex_id = textures_used_last_dump [sel]; + } + } + + if (ImGui::IsItemHovered ()) + { + ImGui::BeginTooltip (); + ImGui::TextColored (ImVec4 (0.7f, 0.9f, 0.3f, 1.0f), "The \"debug\" texture will appear black to make identifying textures to modify easier."); + ImGui::Separator (); + ImGui::BulletText ("Press Ctrl + Shift + [ to select the previous texture from this list"); + ImGui::BulletText ("Press Ctrl + Shift + ] to select the next texture from this list"); + ImGui::EndTooltip (); + } + + ImGui::EndChild (); + + ImGui::SameLine (); + + ImGui::PushStyleVar (ImGuiStyleVar_ChildWindowRounding, 0.0f); + + last_ht = std::max (last_ht, 16L); + last_width = std::max (last_width, 16L); + + ImGui::BeginChild ("SelectedTexture", ImVec2 (std::max (256L, last_width + 24), last_ht + 128), ImGuiWindowFlags_AlwaysAutoResize); + + if (debug_tex_id != 0x00) { + tbf::RenderFix::Texture* pTex = + tbf::RenderFix::tex_mgr.getTexture (debug_tex_id); + + if (pTex != nullptr) { + D3DSURFACE_DESC desc; + + if (SUCCEEDED (pTex->d3d9_tex->GetLevelDesc (0, &desc))) + { + last_width = desc.Width; + last_ht = desc.Height; + + extern std::wstring + SK_D3D9_FormatToStr (D3DFORMAT Format, bool include_ordinal = true); + + + ImGui::Text ( "Dimensions: %lux%lu", + desc.Width, desc.Height/*, + pTex->d3d9_tex->GetLevelCount ()*/ ); + ImGui::Text ( "Format: %ws", + SK_D3D9_FormatToStr (desc.Format).c_str () ); + ImGui::Text ( "Data Size: %.2f MiB", + (double)pTex->size / (1024.0f * 1024.0f) ); + ImGui::Text ( "Load Time: %.6f Seconds", + pTex->load_time / 1000.0f ); + + ImGui::Separator (); + + if (! TBF_IsTextureDumped (debug_tex_id)) + { + if ( ImGui::Button ("Dump Texture to Disk") ) + { + TBF_DumpTexture (desc.Format, debug_tex_id, pTex->d3d9_tex->pTex); + } + } + + else + { + if ( ImGui::Button ("Delete Dumped Texture from Disk") ) + { + TBF_DeleteDumpedTexture (desc.Format, debug_tex_id); + } + } + + ImGui::PushStyleColor (ImGuiCol_Border, ImVec4 (0.8f, 0.95f, 0.1f, 1.0f)); + ImGui::BeginChildFrame (0, ImVec2 ((float)desc.Width + 8, (float)desc.Height + 8), ImGuiWindowFlags_ShowBorders); + ImGui::Image ( pTex->d3d9_tex->pTex, + ImVec2 ((float)desc.Width, (float)desc.Height), + ImVec2 (0,0), ImVec2 (1,1), + ImColor (255,255,255,255), ImColor (255,255,255,128) + ); + ImGui::PopStyleColor (1); + ImGui::EndChildFrame (); + } + } + } + ImGui::EndChild (); + + ImGui::PopStyleVar(2); + + ImGui::TreePop (); + } + + if (ImGui::CollapsingHeader ("Misc. Settings")) + { + ImGui::TreePush (""); + if (ImGui::Checkbox ("Dump ALL Textures (TBFix_Res\\dump\\textures\\\\*.dds)", &config.textures.dump)) tbf::RenderFix::need_reset.graphics = true; + + if (ImGui::IsItemHovered ()) + { + ImGui::BeginTooltip (); + ImGui::Text ("Enabling this will cause the game to run slower and waste disk space, only enable if you know what you are doing."); + ImGui::EndTooltip (); + } + + ImGui::TreePop (); + } + + ImGui::PopItemWidth (); + ImGui::End (); + + return show_dlg; +} \ No newline at end of file diff --git a/src/config.cpp b/src/config.cpp index 45f3336..b3709cc 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -82,6 +82,7 @@ struct { tbf::ParameterFloat* lod_bias; tbf::ParameterBool* cache; tbf::ParameterBool* dump; + tbf::ParameterBool* dump_on_demand; tbf::ParameterInt* cache_size; tbf::ParameterInt* worker_threads; tbf::ParameterBool* show_loading_text; @@ -217,6 +218,16 @@ TBF_LoadConfig (std::wstring name) L"Texture.System", L"Dump" ); + textures.dump_on_demand = + static_cast + (g_ParameterFactory.create_parameter ( + L"Dump Textures on Demand") + ); + textures.dump_on_demand->register_to_ini ( + render_ini, + L"Texture.System", + L"DumpOnDemand" ); + textures.remaster = static_cast (g_ParameterFactory.create_parameter ( @@ -485,6 +496,7 @@ TBF_LoadConfig (std::wstring name) textures.lod_bias->load (config.textures.lod_bias); textures.cache->load (config.textures.cache); textures.dump->load (config.textures.dump); + textures.dump_on_demand->load (config.textures.on_demand_dump); textures.cache_size->load (config.textures.max_cache_in_mib); textures.worker_threads->load (config.textures.worker_threads); textures.show_loading_text->load (config.textures.show_loading_text); @@ -521,6 +533,7 @@ TBF_SaveConfig (std::wstring name, bool close_config) textures.lod_bias->store (config.textures.lod_bias); textures.cache->store (config.textures.cache); textures.dump->store (config.textures.dump); + textures.dump_on_demand->store (config.textures.on_demand_dump); textures.cache_size->store (config.textures.max_cache_in_mib); textures.worker_threads->store (config.textures.worker_threads); textures.show_loading_text->store (config.textures.show_loading_text); diff --git a/src/textures.cpp b/src/textures.cpp index af455de..84a9fd8 100644 --- a/src/textures.cpp +++ b/src/textures.cpp @@ -2214,9 +2214,10 @@ D3DXCreateTextureFromFileInMemoryEx_Detour ( bool resample = false; // Necessary to make D3DX texture write functions work - if ( Pool == D3DPOOL_DEFAULT && config.textures.dump && - (! dumped_textures.count (checksum)) && - (! injectable_textures.count (checksum)) ) + if ( Pool == D3DPOOL_DEFAULT && (config.textures.on_demand_dump || + ( config.textures.dump && + (! dumped_textures.count (checksum)) && + (! injectable_textures.count (checksum)) ) ) ) Usage = D3DUSAGE_DYNAMIC; @@ -2593,12 +2594,75 @@ D3DXCreateTextureFromFileInMemoryEx_Detour ( } if ( config.textures.dump && (! inject_thread) && (! injectable_textures.count (checksum)) && - (! dumped_textures.count (checksum)) ) { + (! dumped_textures.count (checksum)) ) + { D3DXIMAGE_INFO info = { 0 }; D3DXGetImageInfoFromFileInMemory (pSrcData, SrcDataSize, &info); D3DFORMAT fmt_real = info.Format; + TBF_DumpTexture (fmt_real, checksum, *ppTexture); + } + + return hr; +} + +bool +TBF_DeleteDumpedTexture (D3DFORMAT fmt, uint32_t checksum) +{ + wchar_t wszPath [MAX_PATH]; + _swprintf ( wszPath, L"%s\\dump", + TBFIX_TEXTURE_DIR ); + + if (GetFileAttributesW (wszPath) != FILE_ATTRIBUTE_DIRECTORY) + CreateDirectoryW (wszPath, nullptr); + + _swprintf ( wszPath, L"%s\\dump\\textures", + TBFIX_TEXTURE_DIR ); + + if (GetFileAttributesW (wszPath) != FILE_ATTRIBUTE_DIRECTORY) + CreateDirectoryW (wszPath, nullptr); + + _swprintf ( wszPath, L"%s\\%s", + wszPath, + SK_D3D9_FormatToStr (fmt, false).c_str () ); + + if (GetFileAttributesW (wszPath) != FILE_ATTRIBUTE_DIRECTORY) + CreateDirectoryW (wszPath, nullptr); + + wchar_t wszFileName [MAX_PATH] = { L'\0' }; + _swprintf ( wszFileName, L"%s\\dump\\textures\\%s\\%08x%s", + TBFIX_TEXTURE_DIR, + SK_D3D9_FormatToStr (fmt, false).c_str (), + checksum, + TBFIX_TEXTURE_EXT ); + + if (GetFileAttributesW (wszFileName) != INVALID_FILE_ATTRIBUTES) + { + if (DeleteFileW (wszFileName)) + { + dumped_textures.erase (checksum); + return true; + } + } + + return false; +} + +bool +TBF_IsTextureDumped (uint32_t checksum) +{ + return dumped_textures.count (checksum); +} + +HRESULT +TBF_DumpTexture (D3DFORMAT fmt, uint32_t checksum, IDirect3DTexture9* pTex) +{ + if ( (! injectable_textures.count (checksum)) && + (! dumped_textures.count (checksum)) ) + { + D3DFORMAT fmt_real = fmt; + bool compressed = (fmt_real >= D3DFMT_DXT1 && fmt_real <= D3DFMT_DXT5); wchar_t wszPath [MAX_PATH]; @@ -2628,10 +2692,15 @@ D3DXCreateTextureFromFileInMemoryEx_Detour ( checksum, TBFIX_TEXTURE_EXT ); - D3DXSaveTextureToFile (wszFileName, D3DXIFF_DDS, (*ppTexture), NULL); + HRESULT hr = D3DXSaveTextureToFile (wszFileName, D3DXIFF_DDS, pTex, NULL); + + if (SUCCEEDED (hr)) + dumped_textures.insert (checksum); + + return hr; } - return hr; + return E_FAIL; } std::vector remove_textures; diff --git a/tbf.vcxproj b/tbf.vcxproj index ed08ce5..f7a4065 100644 --- a/tbf.vcxproj +++ b/tbf.vcxproj @@ -164,6 +164,8 @@ + + @@ -207,7 +209,6 @@ - diff --git a/tbf.vcxproj.filters b/tbf.vcxproj.filters index 3ce7ea7..2559618 100644 --- a/tbf.vcxproj.filters +++ b/tbf.vcxproj.filters @@ -43,9 +43,6 @@ Source Files - - Source Files\ImGui - Source Files\lzma @@ -169,6 +166,12 @@ Source Files\lzma + + Source Files\ImGui + + + Source Files\ImGui + diff --git a/version.ini b/version.ini index 808ce253c7347d177be86aa22bd849fab0283027..9972750eec978332948fc60a80952b8b385677f3 100644 GIT binary patch delta 142 zcmez4Kf!0iEGAY920aFYiG|ve&oKo#`!S?4lrtzWI5MO#lrbbSQ=M0r`zT7qjFqsR_BYra!agfp=B0Z zY61T~`w8CI8rBBsV(+tBAOjb11s2$vt@0_S52igcA&R*q@8*ZGjbBlzyDK3s1!>~R z3XH&p>;vn#lY*}}MFeLG!D_qogqXfvliF}dPQExPpMm+ z{f%7<3)dvkNN<38)fjP(L40d__|M!GO-CT_IxB}T!>>GbEub$UJ{6-Hn~p=JsM-OT zMy$3^22~76)ik7jQeTLW1mZS`uJdnVEHcFBUx%NopZ<+&w{luPeB*eJi(Rt(u)7FZ zvh*Cs|C&S8Dpd94PM%ap?t)XWoZcjORIQNz-Kmuq(?$6?wLN#iGhMN|ZM-j5A1d$J H?90M82>z5n