mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	fix crashes, add custom texture cache, load textures from load directory
This commit is contained in:
		
							parent
							
								
									f866b2a917
								
							
						
					
					
						commit
						6d90c42a79
					
				
					 16 changed files with 167 additions and 49 deletions
				
			
		|  | @ -164,6 +164,7 @@ void Config::ReadValues() { | ||||||
| 
 | 
 | ||||||
|     // Utility
 |     // Utility
 | ||||||
|     Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false); |     Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false); | ||||||
|  |     Settings::values.custom_textures = sdl2_config->GetBoolean("Utility", "custom_textures", false); | ||||||
| 
 | 
 | ||||||
|     // Audio
 |     // Audio
 | ||||||
|     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); |     Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false); | ||||||
|  |  | ||||||
|  | @ -182,6 +182,10 @@ swap_screen = | ||||||
| # 0 (default): Off, 1: On | # 0 (default): Off, 1: On | ||||||
| dump_textures = | dump_textures = | ||||||
| 
 | 
 | ||||||
|  | # Reads PNG files from load/textures/[Title ID]/ and replaces textures. | ||||||
|  | # 0 (default): Off, 1: On | ||||||
|  | custom_textures = | ||||||
|  | 
 | ||||||
| [Audio] | [Audio] | ||||||
| # Whether or not to enable DSP LLE | # Whether or not to enable DSP LLE | ||||||
| # 0 (default): No, 1: Yes | # 0 (default): No, 1: Yes | ||||||
|  |  | ||||||
|  | @ -231,9 +231,11 @@ void Config::ReadControlValues() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Config::ReadUtilityValues() { | void Config::ReadUtilityValues() { | ||||||
| 
 |  | ||||||
|     qt_config->beginGroup("Utility"); |     qt_config->beginGroup("Utility"); | ||||||
|  | 
 | ||||||
|     Settings::values.dump_textures = ReadSetting("dump_textures", false).toBool(); |     Settings::values.dump_textures = ReadSetting("dump_textures", false).toBool(); | ||||||
|  |     Settings::values.custom_textures = ReadSetting("custom_textures", false).toBool(); | ||||||
|  | 
 | ||||||
|     qt_config->endGroup(); |     qt_config->endGroup(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -704,6 +706,7 @@ void Config::SaveUtilityValues() { | ||||||
|     qt_config->beginGroup("Utility"); |     qt_config->beginGroup("Utility"); | ||||||
| 
 | 
 | ||||||
|     WriteSetting("dump_textures", Settings::values.dump_textures, false); |     WriteSetting("dump_textures", Settings::values.dump_textures, false); | ||||||
|  |     WriteSetting("custom_textures", Settings::values.custom_textures, false); | ||||||
| 
 | 
 | ||||||
|     qt_config->endGroup(); |     qt_config->endGroup(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -88,6 +88,7 @@ void ConfigureGraphics::ApplyConfiguration() { | ||||||
|         static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex()); |         static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex()); | ||||||
|     Settings::values.swap_screen = ui->swap_screen->isChecked(); |     Settings::values.swap_screen = ui->swap_screen->isChecked(); | ||||||
|     Settings::values.dump_textures = ui->toggle_dump_textures->isChecked(); |     Settings::values.dump_textures = ui->toggle_dump_textures->isChecked(); | ||||||
|  |     Settings::values.custom_textures = ui->toggle_custom_textures->isChecked(); | ||||||
|     Settings::values.bg_red = static_cast<float>(bg_color.redF()); |     Settings::values.bg_red = static_cast<float>(bg_color.redF()); | ||||||
|     Settings::values.bg_green = static_cast<float>(bg_color.greenF()); |     Settings::values.bg_green = static_cast<float>(bg_color.greenF()); | ||||||
|     Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); |     Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); | ||||||
|  |  | ||||||
|  | @ -334,6 +334,16 @@ | ||||||
|       <string>Utility</string> |       <string>Utility</string> | ||||||
|      </property> |      </property> | ||||||
|      <layout class="QVBoxLayout" name="verticalLayout_4"> |      <layout class="QVBoxLayout" name="verticalLayout_4"> | ||||||
|  |       <item> | ||||||
|  |        <widget class="QCheckBox" name="toggle_custom_textures"> | ||||||
|  |         <property name="toolTip"> | ||||||
|  |          <string><html><head/><body><p>Replace textures with PNG files.</p><p>Textures are loaded from load/textures/[Title ID]/.</p></body></html></string> | ||||||
|  |         </property> | ||||||
|  |         <property name="text"> | ||||||
|  |          <string>Use Custom Textures (Hardware Renderer only)</string> | ||||||
|  |         </property> | ||||||
|  |        </widget> | ||||||
|  |       </item> | ||||||
|       <item> |       <item> | ||||||
|        <widget class="QCheckBox" name="toggle_dump_textures"> |        <widget class="QCheckBox" name="toggle_dump_textures"> | ||||||
|         <property name="toolTip"> |         <property name="toolTip"> | ||||||
|  | @ -347,19 +357,6 @@ | ||||||
|      </layout> |      </layout> | ||||||
|     </widget> |     </widget> | ||||||
|    </item> |    </item> | ||||||
|    <item> |  | ||||||
|     <spacer name="verticalSpacer"> |  | ||||||
|      <property name="orientation"> |  | ||||||
|       <enum>Qt::Vertical</enum> |  | ||||||
|      </property> |  | ||||||
|      <property name="sizeHint" stdset="0"> |  | ||||||
|       <size> |  | ||||||
|        <width>20</width> |  | ||||||
|        <height>40</height> |  | ||||||
|       </size> |  | ||||||
|      </property> |  | ||||||
|     </spacer> |  | ||||||
|    </item> |  | ||||||
|   </layout> |   </layout> | ||||||
|  </widget> |  </widget> | ||||||
|  <resources/> |  <resources/> | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ | ||||||
| #define DLL_DIR "external_dlls" | #define DLL_DIR "external_dlls" | ||||||
| #define SHADER_DIR "shaders" | #define SHADER_DIR "shaders" | ||||||
| #define DUMP_DIR "dump" | #define DUMP_DIR "dump" | ||||||
|  | #define LOAD_DIR "load" | ||||||
| 
 | 
 | ||||||
| // Filenames
 | // Filenames
 | ||||||
| // Files in the directory returned by GetUserPath(UserPath::LogDir)
 | // Files in the directory returned by GetUserPath(UserPath::LogDir)
 | ||||||
|  |  | ||||||
|  | @ -713,6 +713,7 @@ void SetUserPath(const std::string& path) { | ||||||
|     g_paths.emplace(UserPath::DLLDir, user_path + DLL_DIR DIR_SEP); |     g_paths.emplace(UserPath::DLLDir, user_path + DLL_DIR DIR_SEP); | ||||||
|     g_paths.emplace(UserPath::ShaderDir, user_path + SHADER_DIR DIR_SEP); |     g_paths.emplace(UserPath::ShaderDir, user_path + SHADER_DIR DIR_SEP); | ||||||
|     g_paths.emplace(UserPath::DumpDir, user_path + DUMP_DIR DIR_SEP); |     g_paths.emplace(UserPath::DumpDir, user_path + DUMP_DIR DIR_SEP); | ||||||
|  |     g_paths.emplace(UserPath::LoadDir, user_path + LOAD_DIR DIR_SEP); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const std::string& GetUserPath(UserPath path) { | const std::string& GetUserPath(UserPath path) { | ||||||
|  |  | ||||||
|  | @ -27,6 +27,7 @@ enum class UserPath { | ||||||
|     ConfigDir, |     ConfigDir, | ||||||
|     DLLDir, |     DLLDir, | ||||||
|     DumpDir, |     DumpDir, | ||||||
|  |     LoadDir, | ||||||
|     LogDir, |     LogDir, | ||||||
|     NANDDir, |     NANDDir, | ||||||
|     RootDir, |     RootDir, | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ add_library(core STATIC | ||||||
|     core.h |     core.h | ||||||
|     core_timing.cpp |     core_timing.cpp | ||||||
|     core_timing.h |     core_timing.h | ||||||
|  |     custom_tex_cache.cpp | ||||||
|  |     custom_tex_cache.h | ||||||
|     dumping/backend.cpp |     dumping/backend.cpp | ||||||
|     dumping/backend.h |     dumping/backend.h | ||||||
|     file_sys/archive_backend.cpp |     file_sys/archive_backend.cpp | ||||||
|  |  | ||||||
|  | @ -16,10 +16,14 @@ | ||||||
| #include "core/cheats/cheats.h" | #include "core/cheats/cheats.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/core_timing.h" | #include "core/core_timing.h" | ||||||
|  | <<<<<<< HEAD | ||||||
| #include "core/dumping/backend.h" | #include "core/dumping/backend.h" | ||||||
| #ifdef ENABLE_FFMPEG_VIDEO_DUMPER | #ifdef ENABLE_FFMPEG_VIDEO_DUMPER | ||||||
| #include "core/dumping/ffmpeg_backend.h" | #include "core/dumping/ffmpeg_backend.h" | ||||||
| #endif | #endif | ||||||
|  | ======= | ||||||
|  | #include "core/custom_tex_cache.h" | ||||||
|  | >>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| #include "core/hle/kernel/client_port.h" | #include "core/hle/kernel/client_port.h" | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
|  | @ -146,12 +150,16 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     cheat_engine = std::make_unique<Cheats::CheatEngine>(*this); |     cheat_engine = std::make_unique<Cheats::CheatEngine>(*this); | ||||||
|  | <<<<<<< HEAD | ||||||
|     u64 title_id{0}; |     u64 title_id{0}; | ||||||
|     if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { |     if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | ||||||
|         LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", |         LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", | ||||||
|                   static_cast<u32>(load_result)); |                   static_cast<u32>(load_result)); | ||||||
|     } |     } | ||||||
|     perf_stats = std::make_unique<PerfStats>(title_id); |     perf_stats = std::make_unique<PerfStats>(title_id); | ||||||
|  | ======= | ||||||
|  |     custom_tex_cache = std::make_unique<Core::CustomTexCache>(); | ||||||
|  | >>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory | ||||||
|     status = ResultStatus::Success; |     status = ResultStatus::Success; | ||||||
|     m_emu_window = &emu_window; |     m_emu_window = &emu_window; | ||||||
|     m_filepath = filepath; |     m_filepath = filepath; | ||||||
|  | @ -290,12 +298,21 @@ const Cheats::CheatEngine& System::CheatEngine() const { | ||||||
|     return *cheat_engine; |     return *cheat_engine; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | <<<<<<< HEAD | ||||||
| VideoDumper::Backend& System::VideoDumper() { | VideoDumper::Backend& System::VideoDumper() { | ||||||
|     return *video_dumper; |     return *video_dumper; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const VideoDumper::Backend& System::VideoDumper() const { | const VideoDumper::Backend& System::VideoDumper() const { | ||||||
|     return *video_dumper; |     return *video_dumper; | ||||||
|  | ======= | ||||||
|  | Core::CustomTexCache& System::CustomTexCache() { | ||||||
|  |     return *custom_tex_cache; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const Core::CustomTexCache& System::CustomTexCache() const { | ||||||
|  |     return *custom_tex_cache; | ||||||
|  | >>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) { | void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) { | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <string> | #include <string> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | #include "core/custom_tex_cache.h" | ||||||
| #include "core/frontend/applets/mii_selector.h" | #include "core/frontend/applets/mii_selector.h" | ||||||
| #include "core/frontend/applets/swkbd.h" | #include "core/frontend/applets/swkbd.h" | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
|  | @ -216,7 +217,12 @@ public: | ||||||
|     /// Gets a const reference to the video dumper backend
 |     /// Gets a const reference to the video dumper backend
 | ||||||
|     const VideoDumper::Backend& VideoDumper() const; |     const VideoDumper::Backend& VideoDumper() const; | ||||||
| 
 | 
 | ||||||
|     std::unique_ptr<PerfStats> perf_stats; |     /// Gets a reference to the custom texture cache system
 | ||||||
|  |     Core::CustomTexCache& CustomTexCache(); | ||||||
|  | 
 | ||||||
|  |     /// Gets a const reference to the custom texture cache system
 | ||||||
|  |     const Core::CustomTexCache& CustomTexCache() const; | ||||||
|  | 
 | ||||||
|     FrameLimiter frame_limiter; |     FrameLimiter frame_limiter; | ||||||
| 
 | 
 | ||||||
|     void SetStatus(ResultStatus new_status, const char* details = nullptr) { |     void SetStatus(ResultStatus new_status, const char* details = nullptr) { | ||||||
|  | @ -289,6 +295,9 @@ private: | ||||||
|     /// Video dumper backend
 |     /// Video dumper backend
 | ||||||
|     std::unique_ptr<VideoDumper::Backend> video_dumper; |     std::unique_ptr<VideoDumper::Backend> video_dumper; | ||||||
| 
 | 
 | ||||||
|  |     /// Custom texture cache system
 | ||||||
|  |     std::unique_ptr<Core::CustomTexCache> custom_tex_cache; | ||||||
|  | 
 | ||||||
|     /// RPC Server for scripting support
 |     /// RPC Server for scripting support
 | ||||||
|     std::unique_ptr<RPC::RPCServer> rpc_server; |     std::unique_ptr<RPC::RPCServer> rpc_server; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								src/core/custom_tex_cache.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/core/custom_tex_cache.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | ||||||
|  | #include <stdexcept> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | #include "custom_tex_cache.h" | ||||||
|  | 
 | ||||||
|  | namespace Core { | ||||||
|  | const bool CustomTexCache::IsTextureDumped(const u64 hash) { | ||||||
|  |     return dumped_textures.find(hash) != dumped_textures.end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CustomTexCache::SetTextureDumped(const u64 hash) { | ||||||
|  |     dumped_textures[hash] = true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const bool CustomTexCache::IsTextureCached(const u64 hash) { | ||||||
|  |     return custom_textures.find(hash) != custom_textures.end(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const CustomTexInfo& CustomTexCache::LookupTexture(const u64 hash) { | ||||||
|  |     return custom_textures.at(hash); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CustomTexCache::CacheTexture(const u64 hash, const std::vector<u8>& tex, u32 width, | ||||||
|  |                                   u32 height) { | ||||||
|  |     custom_textures[hash] = {width, height, tex}; | ||||||
|  | } | ||||||
|  | } // namespace Core
 | ||||||
							
								
								
									
										28
									
								
								src/core/custom_tex_cache.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/custom_tex_cache.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <unordered_map> | ||||||
|  | #include <vector> | ||||||
|  | #include "common/common_types.h" | ||||||
|  | 
 | ||||||
|  | namespace Core { | ||||||
|  | struct CustomTexInfo { | ||||||
|  |     u32 width; | ||||||
|  |     u32 height; | ||||||
|  |     std::vector<u8> tex; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // TODO: think of a better name for this class...
 | ||||||
|  | class CustomTexCache { | ||||||
|  | public: | ||||||
|  |     const bool IsTextureDumped(const u64 hash); | ||||||
|  |     void SetTextureDumped(const u64 hash); | ||||||
|  | 
 | ||||||
|  |     const bool IsTextureCached(const u64 hash); | ||||||
|  |     const CustomTexInfo& LookupTexture(const u64 hash); | ||||||
|  |     void CacheTexture(const u64 hash, const std::vector<u8>& tex, u32 width, u32 height); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     std::unordered_map<u64, bool> dumped_textures; | ||||||
|  |     std::unordered_map<u64, CustomTexInfo> custom_textures; | ||||||
|  | }; | ||||||
|  | } // namespace Core
 | ||||||
|  | @ -88,6 +88,7 @@ void LogSettings() { | ||||||
|     LogSetting("Layout_LayoutOption", static_cast<int>(Settings::values.layout_option)); |     LogSetting("Layout_LayoutOption", static_cast<int>(Settings::values.layout_option)); | ||||||
|     LogSetting("Layout_SwapScreen", Settings::values.swap_screen); |     LogSetting("Layout_SwapScreen", Settings::values.swap_screen); | ||||||
|     LogSetting("Utility_DumpTextures", Settings::values.dump_textures); |     LogSetting("Utility_DumpTextures", Settings::values.dump_textures); | ||||||
|  |     LogSetting("Utility_CustomTextures", Settings::values.custom_textures); | ||||||
|     LogSetting("Audio_EnableDspLle", Settings::values.enable_dsp_lle); |     LogSetting("Audio_EnableDspLle", Settings::values.enable_dsp_lle); | ||||||
|     LogSetting("Audio_EnableDspLleMultithread", Settings::values.enable_dsp_lle_multithread); |     LogSetting("Audio_EnableDspLleMultithread", Settings::values.enable_dsp_lle_multithread); | ||||||
|     LogSetting("Audio_OutputEngine", Settings::values.sink_id); |     LogSetting("Audio_OutputEngine", Settings::values.sink_id); | ||||||
|  |  | ||||||
|  | @ -171,6 +171,7 @@ struct Values { | ||||||
|     std::string pp_shader_name; |     std::string pp_shader_name; | ||||||
| 
 | 
 | ||||||
|     bool dump_textures; |     bool dump_textures; | ||||||
|  |     bool custom_textures; | ||||||
| 
 | 
 | ||||||
|     // Audio
 |     // Audio
 | ||||||
|     bool enable_dsp_lle; |     bool enable_dsp_lle; | ||||||
|  |  | ||||||
|  | @ -24,6 +24,7 @@ | ||||||
| #include "common/scope_exit.h" | #include "common/scope_exit.h" | ||||||
| #include "common/vector_math.h" | #include "common/vector_math.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "core/custom_tex_cache.h" | ||||||
| #include "core/frontend/emu_window.h" | #include "core/frontend/emu_window.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
|  | @ -856,7 +857,7 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) { | ||||||
| 
 | 
 | ||||||
| // TODO: move this function to a better place
 | // TODO: move this function to a better place
 | ||||||
| void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height) { | void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height) { | ||||||
|     assert(tex.size() = width * height * 4); |     ASSERT(tex.size() == width * height * 4); | ||||||
|     const u64 line_size = width * 4; |     const u64 line_size = width * 4; | ||||||
|     // Thanks MSVC for not being able to make variable length arrays
 |     // Thanks MSVC for not being able to make variable length arrays
 | ||||||
|     u8* temp_row = new u8[line_size]; |     u8* temp_row = new u8[line_size]; | ||||||
|  | @ -883,38 +884,60 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r | ||||||
| 
 | 
 | ||||||
|     ASSERT(gl_buffer_size == width * height * GetGLBytesPerPixel(pixel_format)); |     ASSERT(gl_buffer_size == width * height * GetGLBytesPerPixel(pixel_format)); | ||||||
| 
 | 
 | ||||||
|     // Decode and dump texture if texture dumping is enabled
 |     // Read custom texture
 | ||||||
|     // or read texture and replace
 |     auto& custom_tex_cache = Core::System::GetInstance().CustomTexCache(); | ||||||
|     bool should_dump = false; |     bool dump_tex = false; | ||||||
|     bool should_use_custom_tex = false; |     bool use_custom_tex = false; | ||||||
|     std::string dump_path; |     std::string dump_path; // Has to be declared here for logging later
 | ||||||
|     std::vector<u8> decoded_png; |     std::vector<u8> decoded_png; | ||||||
|     u32 png_width; |     u32 png_width; | ||||||
|     u32 png_height; |     u32 png_height; | ||||||
|     if (Settings::values.dump_textures) { |     u64 tex_hash = 0; | ||||||
|         dump_path = fmt::format("{}/textures", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir)); | 
 | ||||||
|         if (!FileUtil::IsDirectory(dump_path)) |     if (Settings::values.dump_textures || Settings::values.custom_textures) | ||||||
|             FileUtil::CreateDir(dump_path); |         tex_hash = Common::ComputeHash64(gl_buffer.get(), gl_buffer_size); | ||||||
|         dump_path += fmt::format( | 
 | ||||||
|             "/{:016X}", |     if (Settings::values.custom_textures) { | ||||||
|             Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); |         const std::string load_path = fmt::format( | ||||||
|         if (!FileUtil::IsDirectory(dump_path)) |             "{}textures/{:016X}/tex1_{}x{}_{:016X}_{}.png", | ||||||
|             FileUtil::CreateDir(dump_path); |             FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), | ||||||
|         // Hash the encoded texture
 |             Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, | ||||||
|         const u64 tex_hash = Common::ComputeHash64(gl_buffer.get(), gl_buffer_size); |             width, height, tex_hash, static_cast<u32>(pixel_format)); | ||||||
|         dump_path += fmt::format("/tex1_{}x{}_{:016X}_{}.png", width, height, tex_hash, | 
 | ||||||
|                                  static_cast<u32>(pixel_format)); |         if (!custom_tex_cache.IsTextureCached(tex_hash)) { | ||||||
|         if (!FileUtil::Exists(dump_path)) |             if (FileUtil::Exists(load_path)) { | ||||||
|             should_dump = true; |                 u32 lodepng_ret = lodepng::decode(decoded_png, png_width, png_height, load_path); | ||||||
|         else { |                 if (lodepng_ret) | ||||||
|             u32 lodepng_ret = lodepng::decode(decoded_png, png_width, png_height, dump_path); |                     LOG_CRITICAL(Render_OpenGL, "Failed to load custom texture: {}", | ||||||
|             if (lodepng_ret) |                                  lodepng_error_text(lodepng_ret)); | ||||||
|                 LOG_CRITICAL(Render_OpenGL, "Failed to load custom texture: {}", |                 else { | ||||||
|                              lodepng_error_text(lodepng_ret)); |                     LOG_INFO(Render_OpenGL, "Loaded custom texture from {}", load_path); | ||||||
|             else { |                     FlipRGBA8Texture(decoded_png, png_width, png_height); | ||||||
|                 FlipRGBA8Texture(decoded_png, png_width, png_height); |                     custom_tex_cache.CacheTexture(tex_hash, decoded_png, png_width, png_height); | ||||||
|                 should_use_custom_tex = true; |                     use_custom_tex = true; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |         } else { | ||||||
|  |             const auto custom_tex_info = custom_tex_cache.LookupTexture(tex_hash); | ||||||
|  |             decoded_png = custom_tex_info.tex; | ||||||
|  |             png_width = custom_tex_info.width; | ||||||
|  |             png_height = custom_tex_info.height; | ||||||
|  |             use_custom_tex = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (Settings::values.dump_textures) { | ||||||
|  |         dump_path = fmt::format( | ||||||
|  |             "{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), | ||||||
|  |             Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id); | ||||||
|  |         if (!FileUtil::CreateFullPath(dump_path)) | ||||||
|  |             LOG_ERROR(Render, "Unable to create {}", dump_path); | ||||||
|  | 
 | ||||||
|  |         dump_path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, tex_hash, | ||||||
|  |                                  static_cast<u32>(pixel_format)); | ||||||
|  |         if (!custom_tex_cache.IsTextureDumped(tex_hash) && !FileUtil::Exists(dump_path)) { | ||||||
|  |             custom_tex_cache.SetTextureDumped(tex_hash); | ||||||
|  |             dump_tex = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -929,7 +952,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r | ||||||
|     // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in
 |     // If not 1x scale, create 1x texture that we will blit from to replace texture subrect in
 | ||||||
|     // surface
 |     // surface
 | ||||||
|     OGLTexture unscaled_tex; |     OGLTexture unscaled_tex; | ||||||
|     if (res_scale != 1 && !should_use_custom_tex) { |     if (res_scale != 1 && !use_custom_tex) { | ||||||
|         x0 = 0; |         x0 = 0; | ||||||
|         y0 = 0; |         y0 = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -946,7 +969,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r | ||||||
| 
 | 
 | ||||||
|     // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 |     // Ensure no bad interactions with GL_UNPACK_ALIGNMENT
 | ||||||
|     ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); |     ASSERT(stride * GetGLBytesPerPixel(pixel_format) % 4 == 0); | ||||||
|     if (!should_use_custom_tex) { |     if (!use_custom_tex) { | ||||||
|         glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(stride)); |         glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(stride)); | ||||||
| 
 | 
 | ||||||
|         glActiveTexture(GL_TEXTURE0); |         glActiveTexture(GL_TEXTURE0); | ||||||
|  | @ -968,11 +991,11 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); |     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); | ||||||
|     if (should_dump) { |     if (dump_tex) { | ||||||
|         // Dump texture to RGBA8 and encode as PNG
 |         // Dump texture to RGBA8 and encode as PNG
 | ||||||
|         LOG_INFO(Render_OpenGL, "Dumping texture to {}", dump_path); |         LOG_INFO(Render_OpenGL, "Dumping texture to {}", dump_path); | ||||||
|         std::vector<u8> decoded_texture; |         std::vector<u8> decoded_texture; | ||||||
|         decoded_texture.resize(rect.GetWidth() * rect.GetHeight() * 4); |         decoded_texture.resize(width * height * 4); | ||||||
|         glBindTexture(GL_TEXTURE_2D, target_tex); |         glBindTexture(GL_TEXTURE_2D, target_tex); | ||||||
|         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]); |         glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]); | ||||||
|         glBindTexture(GL_TEXTURE_2D, 0); |         glBindTexture(GL_TEXTURE_2D, 0); | ||||||
|  | @ -982,12 +1005,13 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r | ||||||
|             LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}", |             LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}", | ||||||
|                          lodepng_error_text(png_error)); |                          lodepng_error_text(png_error)); | ||||||
|         } |         } | ||||||
|  |         custom_tex_cache.SetTextureDumped(tex_hash); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     cur_state.texture_units[0].texture_2d = old_tex; |     cur_state.texture_units[0].texture_2d = old_tex; | ||||||
|     cur_state.Apply(); |     cur_state.Apply(); | ||||||
| 
 | 
 | ||||||
|     if (res_scale != 1 && !should_use_custom_tex) { |     if (res_scale != 1 && !use_custom_tex) { | ||||||
|         auto scaled_rect = rect; |         auto scaled_rect = rect; | ||||||
|         scaled_rect.left *= res_scale; |         scaled_rect.left *= res_scale; | ||||||
|         scaled_rect.top *= res_scale; |         scaled_rect.top *= res_scale; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue