diff --git a/src/DivaGL/auth_3d.cpp b/src/DivaGL/auth_3d.cpp index 39e145a..4598b32 100644 --- a/src/DivaGL/auth_3d.cpp +++ b/src/DivaGL/auth_3d.cpp @@ -4,10 +4,10 @@ */ #include "auth_3d.hpp" +#include "../KKdLib/hash.hpp" #include "light_param/fog.hpp" #include "mdl/disp_manager.hpp" #include "rob/rob.hpp" -#include "object.hpp" #include "frame_rate_control.hpp" #include "render_context.hpp" #include "sprite.hpp" @@ -139,6 +139,7 @@ struct auth_3d_curve { auth_3d_key curve; prj::string name; float_t value; + uint32_t type; }; static_assert(sizeof(auth_3d_curve) == 0x70, "\"auth_3d_curve\" struct should have a size of 0x70"); @@ -484,10 +485,10 @@ struct auth_3d { prj::vector object_hrc_list; prj::vector m_object_hrc; prj::vector m_object_hrc_list; - prj::vector field_BE0; - prj::vector object_list_string; - prj::vector object_hrc_list_string; - prj::vector m_object_hrc_list_string; + prj::vector field_BE0; + prj::vector object_list_string; + prj::vector object_hrc_list_string; + prj::vector m_object_hrc_list_string; prj::vector auth_2d; int32_t state; prj::vector field_C60; @@ -495,6 +496,109 @@ struct auth_3d { static_assert(sizeof(auth_3d) == 0xC78, "\"auth_3d\" struct should have a size of 0xC78"); +enum auth_3d_material_list_flags { + AUTH_3D_MATERIAL_LIST_BLEND_COLOR = 0x01, + AUTH_3D_MATERIAL_LIST_EMISSION = 0x02, +}; + +struct auth_3d_material_list { + auth_3d_material_list_flags flags; + auth_3d_rgba blend_color; + auth_3d_rgba emission; + uint64_t hash; +}; + +struct string_range { + char* begin; + char* end; +}; + +struct string_range_capacity { + string_range range; + char* capacity_end; +}; + +struct pair_string_range_string_range { + string_range key; + string_range value; +}; + +static_assert(sizeof(pair_string_range_string_range) == 0x20, "\"CanonicalProperties\" struct should have a size of 0x20"); + +struct CanonicalProperties { + prj::string data; + prj::vector key_value_pair_storage; +}; + +static_assert(sizeof(CanonicalProperties) == 0x38, "\"CanonicalProperties\" struct should have a size of 0x38"); + +struct struc_8 { + float_t max_frame; + void* data; + size_t data_size; + bool field_18; + CanonicalProperties CanProp; + bool field_58; + int32_t field_5C; + int32_t field_60; + int32_t field_64; + int64_t field_68; + bool field_70; + void* binary_data; + size_t binary_size; + bool field_88; +}; + +static_assert(sizeof(struc_8) == 0x90, "\"struc_8\" struct should have a size of 0x90"); + +static string_range* (FASTCALL* CanonicalProperties__GetValueStringRange)( + CanonicalProperties* CanProp, string_range str_rng) + = (string_range * (FASTCALL*)(CanonicalProperties * CanProp, string_range str_rng))0x00000001400AE4F0; +static prj::string* (FASTCALL* CanonicalProperties__GetValueString)( + CanonicalProperties* CanProp, prj::string* str, string_range str_rng) + = (prj::string * (FASTCALL*)(CanonicalProperties * CanProp, prj::string * str, string_range str_rng))0x00000001401AD640; +static void(FASTCALL* auth_3d_rgba__free)(auth_3d_rgba* rgba) += (void(FASTCALL*)(auth_3d_rgba * rgba))0x00000001401B8900; +static void (FASTCALL* auth_3d_rgba__ctrl)(auth_3d_rgba* rgba, float_t frame) + = (void (FASTCALL*)(auth_3d_rgba * rgba, float_t frame))0x00000001401D4070; +static bool (FASTCALL* auth_3d_key__parse)(auth_3d_key* k, struc_8* a2, string_range_capacity str_rng_cap) += (bool (FASTCALL*)(auth_3d_key * k, struc_8 * a2, string_range_capacity str_rng_cap))0x00000001401DB1A0; +static bool (FASTCALL* auth_3d_rgba__parse)(auth_3d_rgba* rgba, struc_8* a2, string_range_capacity str_rng_cap) + = (bool (FASTCALL*)(auth_3d_rgba * rgba, struc_8 * a2, string_range_capacity str_rng_cap))0x00000001401DB520; + +static void auth_3d_material_list_ctrl(auth_3d_material_list* ml, float_t frame); +static bool auth_3d_material_list_parse(auth_3d_material_list* ml, struc_8* a2, string_range_capacity str_rng_cap); +static void auth_3d_set_material_list(auth_3d* auth); +static prj::string string_init_CanonicalProperties_string_range(CanonicalProperties& CanProp, string_range str_rng); +static string_range_capacity string_range_capacity_init_char_ptr(string_range_capacity str_rng_cap, const char* str); + +HOOK(void, FASTCALL, auth_3d_curve_array_free, 0x00000001401C2E30, + prj::vector* vec, auth_3d_curve* begin, auth_3d_curve* end) { + while (begin != end) { + if (begin->name.capacity() >= 0x10) + _operator_delete(((uint64_t**)&begin->name)[0]); + ((uint64_t*)&begin->name)[3] = 15; + ((uint64_t*)&begin->name)[2] = 0; + ((char*)&begin->name)[0] = 0; + + if (begin->type == 1) { + auth_3d_material_list* ml = (auth_3d_material_list*)begin->curve.keys; + auth_3d_rgba__free(&ml->blend_color); + auth_3d_rgba__free(&ml->emission); + delete ml; + } + else { + if (((kft3**)&begin->curve.keys_vec)[0]) { + _operator_delete(((kft3**)&begin->curve.keys_vec)[0]); + ((kft3**)&begin->curve.keys_vec)[0] = 0; + ((kft3**)&begin->curve.keys_vec)[1] = 0; + ((kft3**)&begin->curve.keys_vec)[2] = 0; + } + } + begin++; + } +} + HOOK(void, FASTCALL, auth_3d_m_object_hrc_disp, 0x00000001401D0760, auth_3d_m_object_hrc* moh, auth_3d* auth) { if (!auth->visible || !moh->model_transform.visible) return; @@ -743,8 +847,141 @@ HOOK(void, FASTCALL, auth_3d_object_disp, 0x00000001401D0970, auth_3d_object* o, implOfauth_3d_object_hrc_disp(i, auth); } +HOOK(void, FASTCALL, auth_3d__disp, 0x00000001401D1230, auth_3d* auth) { + if (auth->state != 2 || !auth->enable || auth->bone_mats) + return; + + auth_3d_set_material_list(auth); + originalauth_3d__disp(auth); + disp_manager->set_material_list(); +} + +HOOK(void, FASTCALL, auth_3d_curve__ctrl, 0x00000001401D4140, auth_3d_curve* c, float_t frame) { + if (c->type == 1) + auth_3d_material_list_ctrl((auth_3d_material_list*)c->curve.keys, frame); + else + originalauth_3d_curve__ctrl(c, frame); +} + +HOOK(bool, FASTCALL, auth_3d_curve_parse, 0x00000001401DA230, + auth_3d_curve* c, struc_8* a2, string_range_capacity str_rng_cap) { + string_range_capacity name = string_range_capacity_init_char_ptr(str_rng_cap, ".name"); + c->name.assign(string_init_CanonicalProperties_string_range(a2->CanProp, name.range)); + + string_range_capacity ml_str = string_range_capacity_init_char_ptr(str_rng_cap, ".ml"); + if (CanonicalProperties__GetValueStringRange(&a2->CanProp, ml_str.range)) { + auth_3d_material_list* ml = (auth_3d_material_list*)_operator_new(sizeof(auth_3d_material_list)); + memset(ml, 0, sizeof(auth_3d_material_list)); + auth_3d_material_list_parse(ml, a2, ml_str); + ml->hash = hash_fnv1a64m(c->name.data(), c->name.size()); + c->curve.keys = (kft3*)ml; + c->type = 1; + } + else { + string_range_capacity cv = string_range_capacity_init_char_ptr(str_rng_cap, ".cv"); + auth_3d_key__parse(&c->curve, a2, cv); + c->type = 0; + } + return true; +} + void auth_3d_patch() { + WRITE_MEMORY_STRING(0x00000001401A3DBE, "\x48\x8B" + "\x43\x60\x48\x83\xC3\x70\x48\x83\xC7\x70\x48\x89\x47\xF8\x48\x8D" + "\x43\xF8\x48\x3B\xC6\x75\x8B\x48\x8B\x5C\x24\x30\x48\x8B\xC7\x48" + "\x8B\x74\x24\x38\x48\x83\xC4\x20\x5F\xC3", 0x2C); + WRITE_MEMORY_STRING(0x00000001401A72FF, "\x4C\x89\x40\x38", 0x04); + WRITE_MEMORY_STRING(0x00000001401B316A, "\x48\x8B\x43\x68\x48\x89" + "\x47\x68\x48\x8B\xC7\x48\x8B\x5C\x24\x48\x48\x83\xC4\x30\x5F\xC3", 0x16); + + INSTALL_HOOK(auth_3d_curve_array_free); INSTALL_HOOK(auth_3d_m_object_hrc_disp); INSTALL_HOOK(auth_3d_object_hrc_disp); INSTALL_HOOK(auth_3d_object_disp); + INSTALL_HOOK(auth_3d__disp); + INSTALL_HOOK(auth_3d_curve__ctrl); + INSTALL_HOOK(auth_3d_curve_parse); +} + +static void auth_3d_material_list_ctrl(auth_3d_material_list* ml, float_t frame) { + auth_3d_rgba__ctrl(&ml->blend_color, frame); + auth_3d_rgba__ctrl(&ml->emission, frame); +} + +static bool auth_3d_material_list_parse(auth_3d_material_list* ml, struc_8* a2, string_range_capacity str_rng_cap) { + ml->flags = (auth_3d_material_list_flags)0; + string_range_capacity blend_color = string_range_capacity_init_char_ptr(str_rng_cap, ".blend_color"); + if (CanonicalProperties__GetValueStringRange(&a2->CanProp, blend_color.range)) { + auth_3d_rgba__parse(&ml->blend_color, a2, blend_color); + enum_or(ml->flags, AUTH_3D_MATERIAL_LIST_BLEND_COLOR); + } + + string_range_capacity emission = string_range_capacity_init_char_ptr(str_rng_cap, ".emission"); + if (CanonicalProperties__GetValueStringRange(&a2->CanProp, emission.range)) { + auth_3d_rgba__parse(&ml->emission, a2, emission); + enum_or(ml->flags, AUTH_3D_MATERIAL_LIST_EMISSION); + } + return true; +} + +static void auth_3d_set_material_list(auth_3d* auth) { + int32_t mat_list_count = 0; + material_list_struct mat_list[TEXTURE_PATTERN_COUNT]; + for (auth_3d_curve& i : auth->curve) { + if (i.type != 1) + continue; + + auth_3d_material_list* ml = (auth_3d_material_list*)i.curve.keys; + if (!ml->flags) + continue; + + if (ml->flags & AUTH_3D_MATERIAL_LIST_BLEND_COLOR) { + vec4& blend_color = mat_list[mat_list_count].blend_color; + vec4u8& has_blend_color = mat_list[mat_list_count].has_blend_color; + + blend_color = ml->blend_color.value; + has_blend_color.x = ml->blend_color.has_got[0]; + has_blend_color.y = ml->blend_color.has_got[1]; + has_blend_color.z = ml->blend_color.has_got[2]; + has_blend_color.w = ml->blend_color.has_got[3]; + } + else { + mat_list[mat_list_count].blend_color = {}; + mat_list[mat_list_count].has_blend_color = {}; + } + + if (ml->flags & AUTH_3D_MATERIAL_LIST_EMISSION) { + vec4& emission = mat_list[mat_list_count].emission; + vec4u8& has_emission = mat_list[mat_list_count].has_emission; + + emission = ml->emission.value; + has_emission.x = ml->emission.has_got[0]; + has_emission.y = ml->emission.has_got[1]; + has_emission.z = ml->emission.has_got[2]; + has_emission.w = ml->emission.has_got[3]; + } + else { + mat_list[mat_list_count].emission = {}; + mat_list[mat_list_count].has_emission = {}; + } + + mat_list[mat_list_count].hash = ml->hash; + mat_list_count++; + } + + disp_manager->set_material_list(mat_list_count, mat_list); +} + +static string_range_capacity string_range_capacity_init_char_ptr(string_range_capacity str_rng_cap, const char* str) { + char* end = str_rng_cap.range.end; + while (end != str_rng_cap.capacity_end && *str) + *end++ = *str++; + str_rng_cap.range.end = end; + return str_rng_cap; +} + +static prj::string string_init_CanonicalProperties_string_range(CanonicalProperties& CanProp, string_range str_rng) { + prj::string str; + CanonicalProperties__GetValueString(&CanProp, &str, str_rng); + return str; } diff --git a/src/DivaGL/auth_3d.hpp b/src/DivaGL/auth_3d.hpp index b19bd21..c62405e 100644 --- a/src/DivaGL/auth_3d.hpp +++ b/src/DivaGL/auth_3d.hpp @@ -8,5 +8,6 @@ #include "../KKdLib/default.hpp" #include "../KKdLib/mat.hpp" #include "../KKdLib/vec.hpp" +#include "object.hpp" extern void auth_3d_patch();