From 30e5d12d70ed6c71307ec16f6a337f7b5d5277c7 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Sun, 9 Jun 2024 00:16:44 +0300 Subject: [PATCH] Better upload routine for `Color Change Dw`. Do source texture caching --- src/DivaGL/DivaGL.vcxproj | 3 + src/DivaGL/graphics/color_change_dw.cpp | 333 ++++++++++++++++++++++++ src/DivaGL/graphics/color_change_dw.hpp | 11 + src/DivaGL/hook.cpp | 2 + src/DivaGL/object.cpp | 4 + src/DivaGL/object.hpp | 2 + 6 files changed, 355 insertions(+) create mode 100644 src/DivaGL/graphics/color_change_dw.cpp create mode 100644 src/DivaGL/graphics/color_change_dw.hpp diff --git a/src/DivaGL/DivaGL.vcxproj b/src/DivaGL/DivaGL.vcxproj index 395960d..7ea7ceb 100644 --- a/src/DivaGL/DivaGL.vcxproj +++ b/src/DivaGL/DivaGL.vcxproj @@ -169,6 +169,7 @@ del "$(SolutionDir)bin\$(TargetName).lib" + @@ -228,7 +229,9 @@ del "$(SolutionDir)bin\$(TargetName).lib" + + diff --git a/src/DivaGL/graphics/color_change_dw.cpp b/src/DivaGL/graphics/color_change_dw.cpp new file mode 100644 index 0000000..a7ea4e6 --- /dev/null +++ b/src/DivaGL/graphics/color_change_dw.cpp @@ -0,0 +1,333 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#include "color_change_dw.hpp" +#include "../rob/rob.hpp" +#include "../texture.hpp" +#include + +class ColorChangeDw : public dw::Shell { +public: + dw::ListBox* object_set; + dw::ListBox* texture_name; + dw::Widget* type; + dw::Widget* format; + dw::Widget* size; + dw::Button* show_button; + dw::Button* auto_resize_button; + dw::ListBox* item_chara; + dw::ListBox* item_names; + dw::ListBox* item_texture_names; + dw::Button* over_write; + dw::Button* inverse; + dw::Slider* blend_r; + dw::Slider* blend_g; + dw::Slider* blend_b; + dw::Slider* offset_r; + dw::Slider* offset_g; + dw::Slider* offset_b; + dw::Slider* hue; + dw::Slider* value; + dw::Slider* saturation; + dw::Slider* contrast; + dw::Button* copy_button; + dw::Button* paset_button; + dw::Button* reset_button; + dw::Button* save_button; + dw::RowLayout* row_layout; + int32_t obj_set_index; + int32_t obj_set_id; + bool set; + int32_t color_change_index; + prj::vector<::texture*> texture; + prj::vector<::color_tone> color_tone; + ::color_tone color_tone_temp; + bool show; + bool auto_resize; + ::chara_index chara_index; + int32_t item_index; + size_t item_texture_index; + + ::texture* GetChgTex(); + ::color_tone* GetColorTone(); + void GetColorToneDefault(::color_tone& value); + ::texture* GetOrgTex(); + void GetSetColorTone(); + bool LoadColorTone(); + bool LoadTexture(); + void ReloadData(); + void ResetColorTone(); + void ResetData(); + void ResetTexture(); + void UpdateData(); +}; + +static_assert(sizeof(ColorChangeDw) == 0x2F8, "\"ColorChangeDw\" struct should have a size of 0x2F8"); + +ColorChangeDw*& color_change_dw = *(ColorChangeDw**)0x000000014118FF00; + +prj::vector>* color_change_dw_textures; // Added + +HOOK(void, FASTCALL, ColorChangeDw__ReloadData, 0x00000001402C20B0, ColorChangeDw* _this) { + _this->ReloadData(); +} + +HOOK(void, FASTCALL, ColorChangeDw__Draw, 0x00000001402C2170, ColorChangeDw* _this) { + _this->UpdateData(); + + void (FASTCALL * ColorChangeDw__UpdateTextureInfo)(ColorChangeDw * _this) + = (void (FASTCALL*)(ColorChangeDw * _this))0x00000001402C2C60; + ColorChangeDw__UpdateTextureInfo(_this); + + _this->GetSetColorTone(); + + ::texture* org_tex = _this->GetOrgTex(); + ::texture* chg_tex = _this->GetChgTex(); + ::color_tone* col_tone = _this->GetColorTone(); + + //if (org_tex && chg_tex && col_tone) + // texture_apply_color_tone(org_tex, chg_tex, col_tone); + + // Added + if (org_tex && chg_tex && col_tone + && chg_tex->internal_format == org_tex->internal_format + && chg_tex->width == org_tex->width + && chg_tex->height == org_tex->height + && chg_tex->max_mipmap_level == org_tex->max_mipmap_level) { + prj::vector& vec_data = color_change_dw_textures->data()[_this->color_change_index]; + + for (int32_t i = 0; i <= org_tex->max_mipmap_level; i++) { + int32_t size = org_tex->get_size_mip_level(i); + void* tex_data = vec_data.data()[i]; + if (!tex_data) + continue; + + void* data = prj::HeapCMallocAllocate(prj::HeapCMallocTemp, size, "imgf_color_tone_cpu()"); + if (!data) + break; + + memcpy(data, tex_data, size); + + int32_t width_align = chg_tex->get_width_align_mip_level(i); + int32_t height_align = chg_tex->get_height_align_mip_level(i); + if (chg_tex->flags & TEXTURE_BLOCK_COMPRESSION) { + if (chg_tex->internal_format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT) + dxt1_image_apply_color_tone(width_align, height_align, size, (dxt1_block*)data, col_tone); + else + dxt5_image_apply_color_tone(width_align, height_align, size, (dxt5_block*)data, col_tone); + + gl_state_bind_texture_2d(org_tex->glid); + int32_t width = chg_tex->get_width_mip_level(i); + int32_t height = chg_tex->get_height_mip_level(i); + glCompressedTexSubImage2D(org_tex->target, i, 0, 0, width, height, + org_tex->internal_format, size, data); + } + else if (chg_tex->internal_format == GL_RGB5) { + rgb565_image_apply_color_tone(width_align, height_align, size, (rgb565*)data, col_tone); + + gl_state_bind_texture_2d(org_tex->glid); + int32_t width = chg_tex->get_width_mip_level(i); + int32_t height = chg_tex->get_height_mip_level(i); + glTexSubImage2DDLL(org_tex->target, i, 0, 0, width, height, + GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + } + gl_state_get_error(); + prj::HeapCMallocFree(prj::HeapCMallocTemp, data); + } + gl_state_bind_texture_2d(0); + } + + if (_this->show) { + if (org_tex) { + spr::SprArgs args; + args.texture = org_tex; + if (_this->auto_resize) + args.SetSpriteSize({ 256.0f, 256.0f }); + spr::put_sprite(&args); + } + + if (chg_tex) { + spr::SprArgs args; + args.texture = chg_tex; + args.trans.x = (float_t)chg_tex->width; + if (_this->auto_resize) { + args.SetSpriteSize({ 256.0f, 256.0f }); + args.trans.x = 266.0f; + } + spr::put_sprite(&args); + } + } + + _this->dw::Shell::Draw(); +} + +HOOK(void, FASTCALL, ColorChangeDw__ResetData, 0x00000001402C4130, ColorChangeDw* _this) { + _this->ResetData(); +} + +void color_change_dw_patch() { + color_change_dw_textures = new prj::vector>(); // Added + + INSTALL_HOOK(ColorChangeDw__ReloadData); + INSTALL_HOOK(ColorChangeDw__Draw); + INSTALL_HOOK(ColorChangeDw__ResetData); +} + +::texture* ColorChangeDw::GetChgTex() { + if (color_change_index >= 0 && color_change_index < texture.size()) + return texture.data()[color_change_index]; + return 0; +} + +::color_tone* ColorChangeDw::GetColorTone() { + if (color_change_index >= 0 && color_change_index < color_tone.size()) + return &color_tone.data()[color_change_index]; + return 0; +} + +void ColorChangeDw::GetColorToneDefault(::color_tone& value) { + value = {}; +} + +::texture* ColorChangeDw::GetOrgTex() { + ::texture** textures = objset_info_storage_get_set_textures(obj_set_id); + if (textures && color_change_index < objset_info_storage_get_set_tex_num(obj_set_id)) + return textures[color_change_index]; + return 0; +} + +void ColorChangeDw::GetSetColorTone() { + ::color_tone* col_tone = GetColorTone(); + if (col_tone) { + inverse->SetValue(col_tone->inverse); + blend_r->scroll_bar->SetValue(col_tone->blend.x); + blend_g->scroll_bar->SetValue(col_tone->blend.y); + blend_b->scroll_bar->SetValue(col_tone->blend.z); + offset_r->scroll_bar->SetValue(col_tone->offset.x); + offset_g->scroll_bar->SetValue(col_tone->offset.y); + offset_b->scroll_bar->SetValue(col_tone->offset.z); + hue->scroll_bar->SetValue(col_tone->hue); + saturation->scroll_bar->SetValue(col_tone->saturation); + value->scroll_bar->SetValue(col_tone->value); + contrast->scroll_bar->SetValue(col_tone->contrast); + } +} + +bool ColorChangeDw::LoadColorTone() { + ResetColorTone(); + + if (!texture.size()) + return false; + + ::color_tone col_tone; + GetColorToneDefault(col_tone); + color_tone.resize(texture.size(), col_tone); + return true; +} + +bool ColorChangeDw::LoadTexture() { + ResetTexture(); + + ::texture** textures = objset_info_storage_get_set_textures(obj_set_id); + if (!textures) + return false; + + int32_t tex_num = objset_info_storage_get_set_tex_num(obj_set_id); + + /*for (int32_t i = 0; i < tex_num; i++) { + ::texture* chg_tex = 0; + ::texture* org_tex = textures[i]; + if (org_tex->target == GL_TEXTURE_2D) { + chg_tex = texture_create_copy_texture(texture_id(0x22, i), org_tex); + if (!chg_tex) + break; + } + + texture.push_back(chg_tex); + }*/ + + // Added + texture.reserve(tex_num); + color_change_dw_textures->reserve(tex_num); + for (int32_t i = 0; i < tex_num; i++) { + color_change_dw_textures->push_back({}); + + ::texture* chg_tex = 0; + ::texture* org_tex = textures[i]; + if (org_tex->target == GL_TEXTURE_2D) { + prj::vector& vec_data = color_change_dw_textures->back(); + vec_data.reserve((size_t)org_tex->max_mipmap_level + 1); + for (int32_t i = 0; i <= org_tex->max_mipmap_level; i++) { + int32_t size = org_tex->get_size_mip_level(i); + void* data = prj::HeapCMallocAllocate(prj::HeapCMallocTemp, size, "ColorChangeDw::LoadTexture()"); + if (!data) + break; + + int32_t width_align = org_tex->get_width_align_mip_level(i); + int32_t height_align = org_tex->get_height_align_mip_level(i); + gl_state_bind_texture_2d(org_tex->glid); + if (org_tex->flags & TEXTURE_BLOCK_COMPRESSION) + glGetCompressedTexImage(org_tex->target, i, data); + else + glGetTexImageDLL(org_tex->target, i, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + gl_state_get_error(); + vec_data.push_back(data); + } + + chg_tex = texture_load_tex_2d(texture_id(0x22, i), org_tex->internal_format, + org_tex->width, org_tex->height, org_tex->max_mipmap_level, vec_data.data(), true); + + if (!chg_tex) + break; + } + + texture.push_back(chg_tex); + } + return true; +} + +void ColorChangeDw::ReloadData() { + ResetData(); + if (LoadTexture() && LoadColorTone()) + set = true; + else + ResetData(); +} + +void ColorChangeDw::ResetColorTone() { + color_tone.clear(); +} + +void ColorChangeDw::ResetData() { + set = false; + ResetTexture(); + ResetColorTone(); +} + +void ColorChangeDw::ResetTexture() { + for (::texture*& i : texture) { + texture_release(i); + i = 0; + } + texture.clear(); + + // Added + for (prj::vector& i : *color_change_dw_textures) + for (void*& j : i) + if (j) { + prj::HeapCMallocFree(prj::HeapCMallocTemp, j); + j = 0; + } + + color_change_dw_textures->clear(); +} + +void ColorChangeDw::UpdateData() { + if (!set) + ReloadData(); + else if (!objset_info_storage_get_set_textures(obj_set_id)) + ResetData(); + +} \ No newline at end of file diff --git a/src/DivaGL/graphics/color_change_dw.hpp b/src/DivaGL/graphics/color_change_dw.hpp new file mode 100644 index 0000000..d63294e --- /dev/null +++ b/src/DivaGL/graphics/color_change_dw.hpp @@ -0,0 +1,11 @@ +/* + by korenkonder + GitHub/GitLab: korenkonder +*/ + +#pragma once + +#include "../../KKdLib/default.hpp" +#include "../dw.hpp" + +extern void color_change_dw_patch(); diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp index 8e7600b..a3618d5 100644 --- a/src/DivaGL/hook.cpp +++ b/src/DivaGL/hook.cpp @@ -6,6 +6,7 @@ #include "hook.hpp" #include "Glitter/glitter.hpp" #include "data_test/rob_osage_test.hpp" +#include "graphics/color_change_dw.hpp" #include "mdl/disp_manager.hpp" #include "pv_game/pv_game.hpp" #include "rob/rob.hpp" @@ -56,6 +57,7 @@ HOOK(int32_t, FASTCALL, data_init, 0x0000000140192FF0) { auth_3d_patch(); camera_patch(); + color_change_dw_patch(); mdl::disp_manager_patch(); effect_patch(); light_param_patch(); diff --git a/src/DivaGL/object.cpp b/src/DivaGL/object.cpp index a5e7887..3245ebb 100644 --- a/src/DivaGL/object.cpp +++ b/src/DivaGL/object.cpp @@ -77,6 +77,10 @@ int32_t(FASTCALL* object_database_get_set_id)(int32_t set_index) = (int32_t(FASTCALL*)(int32_t set_index))0x000000014045AA10; int32_t(FASTCALL* object_database_get_object_set_id)(const char* name) = (int32_t(FASTCALL*)(const char* name))0x000000014045AA60; +int32_t(FASTCALL* objset_info_storage_get_set_tex_num)(int32_t set) + = (int32_t(FASTCALL*)(int32_t set))0x000000014045ADE0; +texture** (FASTCALL* objset_info_storage_get_set_textures)(int32_t set) + = (texture * *(FASTCALL*)(int32_t set))0x000000014045AE20; int32_t(FASTCALL* objset_info_storage_load_set)(int32_t set) = (int32_t(FASTCALL*)(int32_t set))0x000000014045C6A0; bool (FASTCALL* objset_info_storage_load_obj_set_check_not_read)(int32_t set) diff --git a/src/DivaGL/object.hpp b/src/DivaGL/object.hpp index 58b52eb..7e31c7c 100644 --- a/src/DivaGL/object.hpp +++ b/src/DivaGL/object.hpp @@ -596,6 +596,8 @@ extern GLuint(FASTCALL* objset_info_storage_get_set_texture)(int32_t set, int32_ extern prj::vector* (FASTCALL* objset_info_storage_get_set_gentex)(int32_t set); extern int32_t(FASTCALL* object_database_get_set_id)(int32_t set_index); extern int32_t(FASTCALL* object_database_get_object_set_id)(const char* name); +extern int32_t(FASTCALL* objset_info_storage_get_set_tex_num)(int32_t set); +extern texture** (FASTCALL* objset_info_storage_get_set_textures)(int32_t set); extern int32_t(FASTCALL* objset_info_storage_load_set)(int32_t set); extern bool (FASTCALL* objset_info_storage_load_obj_set_check_not_read)(int32_t set);