From e5418a847ba679068b9e74f3eb75fe3097e7cdf4 Mon Sep 17 00:00:00 2001 From: korenkonder Date: Tue, 2 Apr 2024 23:51:10 +0300 Subject: [PATCH] Init render data by DivaGL --- src/DivaGL/hook.cpp | 1 + src/DivaGL/render.cpp | 10 + src/DivaGL/render.hpp | 1 + src/DivaGL/render_context.cpp | 19 ++ src/DivaGL/render_context.hpp | 2 + src/DivaGL/render_manager.cpp | 180 ++++++++++++++++++ src/DivaGL/render_manager.hpp | 1 + src/DivaGL/shadow.cpp | 346 +++++++++++++++++++++++++++++++++- src/DivaGL/shadow.hpp | 8 + 9 files changed, 566 insertions(+), 2 deletions(-) diff --git a/src/DivaGL/hook.cpp b/src/DivaGL/hook.cpp index b163236..08585b2 100644 --- a/src/DivaGL/hook.cpp +++ b/src/DivaGL/hook.cpp @@ -56,6 +56,7 @@ HOOK(int32_t, FASTCALL, data_init, 0x0000000140192FF0) { render_manager_patch(); rob_patch(); pv_game_patch(); + shadow_patch(); sprite_patch(); stage_patch(); texture_patch(); diff --git a/src/DivaGL/render.cpp b/src/DivaGL/render.cpp index cd0de09..62c3ffb 100644 --- a/src/DivaGL/render.cpp +++ b/src/DivaGL/render.cpp @@ -1014,6 +1014,16 @@ namespace rndr { } } + void Render::set_screen_res(int32_t x_offset, int32_t y_offset, int32_t width, int32_t height) { + screen_x_offset = x_offset; + screen_y_offset = y_offset; + screen_width = min_def(width, this->width); + screen_height = min_def(height, this->height); + + update_res(false, -1); + update = 1; + } + void Render::take_ss(texture* tex, bool vertical, float_t horizontal_offset) { int32_t index = render_texture_set(tex, true); if (index < 0) diff --git a/src/DivaGL/render.hpp b/src/DivaGL/render.hpp index 79c4626..3cc4f60 100644 --- a/src/DivaGL/render.hpp +++ b/src/DivaGL/render.hpp @@ -191,6 +191,7 @@ namespace rndr { int32_t render_texture_set(texture* render_texture, bool task_photo); void render_texture_free(texture* render_texture, bool task_photo); void resize(int32_t width, int32_t height); + void set_screen_res(int32_t x_offset, int32_t y_offset, int32_t width, int32_t height); void take_ss(texture* tex, bool vertical, float_t horizontal_offset); void transparency_combine(float_t alpha); void transparency_copy(); diff --git a/src/DivaGL/render_context.cpp b/src/DivaGL/render_context.cpp index 3fc747b..5362803 100644 --- a/src/DivaGL/render_context.cpp +++ b/src/DivaGL/render_context.cpp @@ -23,6 +23,25 @@ void draw_state_stats::reset() { field_1C = 0; } +void sss_data::free() { + if (init_data) + for (RenderTexture& i : textures) + i.Free(); +} + +void sss_data::init() { + if (init_data) + return; + + textures[0].Init(640, 360, 0, GL_RGBA16F, GL_ZERO /*GL_DEPTH_COMPONENT32F*/); + textures[1].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); + textures[2].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); + textures[3].Init(320, 180, 0, GL_RGBA16F, GL_ZERO); + + param = { 0.0f, 0.0f, 0.0f, 1.0f }; + init_data = true; +} + void sss_data::set_texture(int32_t texture_index) { gl_state_active_bind_texture_2d(16, textures[texture_index].GetColorTex()); gl_state_active_texture(0); diff --git a/src/DivaGL/render_context.hpp b/src/DivaGL/render_context.hpp index 9eddecd..45ca254 100644 --- a/src/DivaGL/render_context.hpp +++ b/src/DivaGL/render_context.hpp @@ -39,6 +39,8 @@ struct sss_data { RenderTexture textures[4]; vec4 param; + void free(); + void init(); void set_texture(int32_t); }; diff --git a/src/DivaGL/render_manager.cpp b/src/DivaGL/render_manager.cpp index ed8099f..f4a5730 100644 --- a/src/DivaGL/render_manager.cpp +++ b/src/DivaGL/render_manager.cpp @@ -44,6 +44,9 @@ static void draw_pass_3d_translucent_has_objects(bool* arr, mdl::ObjType type); static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, blur_filter_mode filter, const vec2 res_scale, const vec4 scale, const vec4 offset); +static void render_manager_free_render_textures(); +static void render_manager_init_render_textures(int32_t multisample); + extern render_context* rctx; RenderTexture* litproj_shadow = (RenderTexture*)0x0000000141194DA0; @@ -51,6 +54,26 @@ RenderTexture* litproj_texture = (RenderTexture*)0x0000000141194E00; rndr::RenderManager* render_manager = (rndr::RenderManager*)0x00000001411AD320; namespace rndr { + struct RenderTextureData { + GLenum type; + int32_t width; + int32_t height; + int32_t max_level; + GLenum color_format; + GLenum depth_format; + }; + + static const RenderTextureData render_manager_render_texture_data_array[] = { + { GL_TEXTURE_2D, 0x200, 0x100, 0, GL_RGBA8 , GL_DEPTH_COMPONENT24 }, + { GL_TEXTURE_2D, 0x200, 0x100, 0, GL_RGBA16F, GL_DEPTH_COMPONENT24 }, + { GL_TEXTURE_2D, 0x400, 0x400, 0, GL_RGBA8 , GL_ZERO }, + { GL_TEXTURE_2D, 0x400, 0x400, 0, GL_RGBA8 , GL_ZERO }, + { GL_TEXTURE_2D, 0x400, 0x400, 0, GL_RGBA8 , GL_ZERO }, + { GL_TEXTURE_2D, 0x100, 0x100, 0, GL_RGBA8 , GL_ZERO }, + { GL_TEXTURE_2D, 0x100, 0x100, 0, GL_RGBA32F, GL_ZERO }, + { GL_TEXTURE_2D, 0x100, 0x100, 0, GL_RGBA8 , GL_ZERO }, + }; + static const int32_t render_manager_render_texture_index_array[][3] = { { 1, 1, 1 }, { 0, 0, 0 }, @@ -81,6 +104,65 @@ namespace rndr { return render_textures[render_manager_render_texture_index_array[index][tex_index[index]]]; } + void RenderManager::reset() { + for (int32_t i = 0; i < RND_PASSID_NUM; i++) { + pass_sw[i] = true; + cpu_time[i] = 0.0; + gpu_time[i] = 0.0; + } + + set_pass_sw(RND_PASSID_2, 0); + set_pass_sw(RND_PASSID_REFLECT, 0); + set_pass_sw(RND_PASSID_REFRACT, 0); + set_pass_sw(RND_PASSID_PRE_PROCESS, 0); + set_pass_sw(RND_PASSID_SHOW_VECTOR, 0); + + shadow_ptr = 0; + sync_gpu = false; + time.get_timestamp(); + + shadow = true; + opaque_z_sort = true; + alpha_z_sort = true; + field_11F = false; + field_120 = false; + + reflect_blur_num = 1; + reflect_blur_filter = BLUR_FILTER_4; + show_ref_map = false; + + reflect_type = STAGE_DATA_REFLECT_DISABLE; + check_state = false; + show_vector_flags = 0; + show_vector_length = 0.05f; + show_vector_z_offset = 0.0f; + show_stage_shadow = false; + effect_texture = 0; + + reflect = false; + refract = false; + npr_param = 0; + field_31C = false; + field_31D = false; + field_31E = false; + field_31F = false; + field_320 = false; + + for (bool& i : draw_pass_3d) + i = true; + + field_11E = false; + clear = false; + + width = 0; + height = 0; + multisample_framebuffer = 0; + multisample_renderbuffer = 0; + multisample = true; + + npr = false; + } + void RenderManager::resize(int32_t width, int32_t height) { if (this->width == width && this->height == height) return; @@ -1093,6 +1175,15 @@ HOOK(void, FASTCALL, render_manager_init_render_textures, 0x0000000140502560, in gl_state_bind_framebuffer(0); } +HOOK(void, FASTCALL, render_manager_free_data, 0x0000000140502770) { + render_manager_free_render_textures(); + render_manager->render->free(); + + shadow_ptr_free(); + + sss_data_get()->free(); +} + HOOK(void, FASTCALL, render_manager_free_render_textures, 0x00000001405027A0) { rndr::RenderManager& render_manager = *::render_manager; @@ -1110,9 +1201,40 @@ HOOK(void, FASTCALL, render_manager_free_render_textures, 0x00000001405027A0) { i.Free(); } +HOOK(void, FASTCALL, render_manager_init_data, 0x0000000140502A10, int32_t ssaa, int32_t hd_res, int32_t ss_alpha_mask, bool npr) { + rndr::RenderManager& render_manager = *::render_manager; + + render_manager.reset(); + render_manager.npr = npr; + render_texture_counter_reset(); + + resolution_struct* res_wind = res_window_get(); + resolution_struct* res_wind_int = res_window_internal_get(); + render_manager.render = render_get(); + render_manager.render->init_render_buffers(res_wind_int->width, res_wind_int->height, ssaa, hd_res, ss_alpha_mask); + render_manager.render->set_screen_res(res_wind_int->x_offset, + res_wind_int->y_offset, res_wind_int->width, res_wind_int->height); + render_manager.width = res_wind->width; + render_manager.height = res_wind->height; + render_manager_init_render_textures(1); + render_manager.render->init_tone_map_buffers(); + + shadow_ptr_init(); + render_manager.shadow_ptr = shadow_ptr_get(); + render_manager.shadow_ptr->init(); + + sss_data_get()->init(); + + void(FASTCALL * sub_1403B6CC0)() = (void(FASTCALL*)())0x00000001403B6CC0; + sub_1403B6CC0(); + + glGetErrorDLL(); +} + void render_manager_patch() { INSTALL_HOOK(render_manager_init_render_textures); INSTALL_HOOK(render_manager_free_render_textures); + INSTALL_HOOK(render_manager_init_data); } static void draw_pass_shadow_begin_make_shadowmap(Shadow* shad, int32_t index, int32_t a3) { @@ -1790,3 +1912,61 @@ static void blur_filter_apply(RenderTexture* dst, RenderTexture* src, gl_state_bind_sampler(0, rctx->render_samplers[0]); shaders_ft.draw_arrays(GL_TRIANGLE_STRIP, (GLint)(filter * 4LL), 4); } + +static void render_manager_free_render_textures() { + rndr::RenderManager& render_manager = *::render_manager; + + if (render_manager.multisample_renderbuffer) { + glDeleteRenderbuffers(1, &render_manager.multisample_renderbuffer); + render_manager.multisample_renderbuffer = 0; + } + + if (render_manager.multisample_framebuffer) { + glDeleteFramebuffers(1, &render_manager.multisample_framebuffer); + render_manager.multisample_framebuffer = 0; + } + + for (RenderTexture& i : render_manager.render_textures) + i.Free(); +} + +static void render_manager_init_render_textures(int32_t multisample) { + rndr::RenderManager& render_manager = *::render_manager; + + if (multisample) { + glGenFramebuffers(1, &render_manager.multisample_framebuffer); + glGenRenderbuffers(1, &render_manager.multisample_renderbuffer); + + gl_state_bind_framebuffer(render_manager.multisample_framebuffer); + glBindRenderbuffer(GL_RENDERBUFFER, render_manager.multisample_renderbuffer); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, + GL_RGBA8, render_manager.width, render_manager.height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, render_manager.multisample_renderbuffer); + glDrawBufferDLL(GL_COLOR_ATTACHMENT0); + glDrawBufferDLL(GL_COLOR_ATTACHMENT0); + gl_state_bind_framebuffer(0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + if (glGetErrorDLL()) { + glDeleteRenderbuffers(1, &render_manager.multisample_renderbuffer); + render_manager.multisample_renderbuffer = 0; + glDeleteFramebuffers(1, &render_manager.multisample_framebuffer); + render_manager.multisample_framebuffer = 0; + } + } + + for (int32_t i = 0; i < 9; i++) { + const rndr::RenderTextureData* tex_data = &rndr::render_manager_render_texture_data_array[i]; + if (tex_data->type != GL_TEXTURE_2D) + continue; + + RenderTexture& rt = render_manager.render_textures[i]; + rt.Init(tex_data->width, tex_data->height, tex_data->max_level, + tex_data->color_format, tex_data->depth_format); + rt.Bind(); + glClearColorDLL(0.0f, 0.0f, 0.0f, 0.0f); + glClearDLL(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + gl_state_bind_framebuffer(0); +} diff --git a/src/DivaGL/render_manager.hpp b/src/DivaGL/render_manager.hpp index 33bfa19..1f7d400 100644 --- a/src/DivaGL/render_manager.hpp +++ b/src/DivaGL/render_manager.hpp @@ -103,6 +103,7 @@ namespace rndr { void add_pre_process(int32_t type, void(*func)(void*), void* data); void clear_pre_process(int32_t type); RenderTexture& get_render_texture(int32_t index); + void reset(); void resize(int32_t width, int32_t height); void set_clear(bool value); void set_effect_texture(texture* value); diff --git a/src/DivaGL/shadow.cpp b/src/DivaGL/shadow.cpp index bd1a03e..bfe96a1 100644 --- a/src/DivaGL/shadow.cpp +++ b/src/DivaGL/shadow.cpp @@ -4,16 +4,358 @@ */ #include "shadow.hpp" +#include "render_context.hpp" +#include "render_manager.hpp" +#include -Shadow** shadow_ptr = (Shadow**)0x000000014CC587B8; +Shadow*& shadow_ptr = *(Shadow**)0x000000014CC587B8; void(FASTCALL* sub_1405E8A20)(Shadow* shad, int32_t index, vec3* pos) = (void(FASTCALL*)(Shadow* shad, int32_t index, vec3 * pos))0x00000001405E8A20; +void(FASTCALL* shadow_ptr_free)() = (void(FASTCALL*)())0x00000001405E8610; +void(FASTCALL* shadow_ptr_init)() = (void(FASTCALL*)())0x00000001405E8890; + +void Shadow::ctrl() { + for (int32_t i = 0; i < 2; i++) + light_enable[i] = false; + + if (render_manager->shadow) { + view_mat[0] = camera_data->view; + view_mat[1] = camera_data->inv_view; + + light_data& light_chara = light_set_data[LIGHT_SET_MAIN].lights[LIGHT_CHARA]; + + vec3 position; + light_chara.get_position(position); + float_t length = vec3::length(position); + if (length < 0.000001f) + direction = { 0.0f, 1.0f, 0.0f }; + else + direction = -position * (1.0f / length); + + for (int32_t i = 0; i < 2; i++) + if (disp_manager->get_obj_count((mdl::ObjType)(mdl::OBJ_TYPE_SHADOW_CHARA + i))) + light_enable[i] = true; + } + + int32_t count = 0; + num_light = 0; + for (int32_t i = 0; i < 2; i++) + if (light_enable[i] && field_1D0[i].size() > 0) { + num_light++; + count += (int32_t)field_1D0[i].size(); + } + else + light_enable[i] = false; + + if (count < 3) { + for (int32_t i = 0; i < 2; i++) { + field_1A8[i] = 0.0f; + field_1C8[i] = 0.0f; + if (!light_enable[i] || field_1D0[i].size() < 1) + continue; + + vec3 v7 = 0.0f; + for (vec3& j : field_1D0[i]) + v7 += j; + + float_t v14 = (float_t)(int64_t)field_1D0[i].size(); + if (v14 < 0.0f) + v14 += (float_t)UINT64_MAX; + v7 *= 1.0f / v14; + + float_t v15 = 0.0f; + for (vec3& j : field_1D0[i]) { + vec3 v22 = v7 - j; + vec3 v25 = direction * vec3::dot(v22, direction); + float_t v24 = vec3::distance(v25, v22); + v24 -= 0.25f; + if (v24 < 0.0f) + v24 = 0.0f; + if (v15 < v24) + v15 = v24; + } + field_1A8[i] = v7; + field_1C8[i] = v15; + } + + if (num_light > 0) { + vec3 view_point = 0.0f; + vec3 interest = 0.0f; + for (int32_t i = 0; i < 2; i++) { + if (!light_enable[i]) + continue; + + vec3 v11 = field_1A8[i] - direction * field_208; + float_t v9 = vec3::distance(this->view_point[i], v11); + float_t v12 = vec3::distance(this->interest[i], field_1A8[i]); + if (v9 > 0.1f || v12 > 0.1f) { + this->view_point[i] = v11; + this->interest[i] = field_1A8[i]; + } + + view_point += this->view_point[i]; + interest += this->interest[i]; + } + + view_point_shared = view_point * (1.0f / (float_t)num_light); + interest_shared = interest * (1.0f / (float_t)num_light); + } + + float_t v2 = max_def(field_1C8[0], field_1C8[1]); + separate = false; + shadow_range = v2 + 1.2f; + field_200[0] = 0; + field_200[1] = 1; + if (num_light >= 2) { + vec3 v12 = field_1A8[0] - interest_shared; + vec3 v14 = field_1A8[1] - interest_shared; + + float_t v6 = vec3::length(direction * vec3::dot(v12, direction) - v12); + + float_t v16 = v6 - 0.25f; + if (v16 < 0.0f) + v16 = 0.0f; + + if (v16 > 1.2f) { + shadow_range = v2 + 2.4f; + separate = true; + } + else + shadow_range = v2 + 1.2f + v16; + + if (vec3::dot(v12, direction) < vec3::dot(v14, direction)) { + field_200[1] = 0; + field_200[0] = 1; + } + } + } + else { + vec3 v3; + vec3 v86; + if (direction.y * direction.y < 0.99f) { + v86 = vec3::cross(direction, vec3(0.0f, 1.0f, 0.0f)); + v3 = vec3::normalize(vec3::cross(v86, direction)); + v86 = vec3::normalize(v86); + } + else { + v3 = { 0.0f, 0.0f, 1.0f }; + v86 = { 1.0f, 0.0f, 0.0f }; + } + + for (int32_t i = 0; i < 2; i++) { + field_1A8[i] = 0.0f; + field_1C8[i] = 0.0; + if (!light_enable[i] || field_1D0[i].size() < 1) + continue; + + vec3 v22 = 0.0f; + for (vec3& j : field_1D0[i]) + v22 += j; + + float_t v29 = (float_t)(int64_t)field_1D0[i].size(); + if (v29 < 0.0f) + v29 += (float_t)UINT64_MAX; + + float_t v30 = 0.0f; + vec3 v31 = v22 * (1.0f / v29); + + for (vec3& j : field_1D0[i]) { + vec3 v34 = v31 - j; + float_t v38 = fabsf(vec3::dot(v34, v3)); + float_t v39 = fabsf(vec3::dot(v34, v86)); + if (v39 >= v38) + v38 = v39; + if (v30 < v38) + v30 = v38; + } + field_1A8[i] = v31; + field_1C8[i] = v30; + } + + if (num_light > 0) { + for (int32_t i = 0; i < 2; i++) { + if (!light_enable[i]) + continue; + + vec3 v53 = field_1A8[i] - direction * field_208; + float_t v51 = vec3::distance(view_point[i], v53); + float_t v54 = vec3::distance(interest[i], field_1A8[i]); + if (v51 > 0.1f || v54 > 0.1f) { + view_point[i] = v53; + interest[i] = field_1A8[i]; + } + } + + vec3 view_point = 0.0f; + vec3 interest = 0.0f; + int32_t count = 0; + for (int32_t i = 0; i < 2; i++) { + int32_t c = (int32_t)field_1D0[i].size(); + view_point += this->view_point[i] * (float_t)c; + interest += this->interest[i] * (float_t)c; + count += c; + } + + view_point_shared = view_point * (1.0f / (float_t)count); + interest_shared = interest * (1.0f / (float_t)count); + } + + float_t v2 = 0.0f; + float_t v67 = max_def(field_1C8[0], field_1C8[1]); + separate = false; + shadow_range = v67 + 1.2f; + field_200[0] = 0; + field_200[1] = 1; + if (num_light >= 2) { + float_t v68 = 0.0f; + float_t v69 = 0.0f; + float_t v70 = 0.0f; + for (int32_t i = 0; i < 2; i++) { + if (!light_enable[i]) + continue; + + for (vec3& j : field_1D0[i]) { + vec3 v74 = j - interest_shared; + + float_t v77 = vec3::dot(v74, v86); + if (v2 > v77) + v2 = v77; + else if (v69 < v77) + v69 = v77; + + float_t v78 = vec3::dot(v74, v3); + if (v68 > v78) + v68 = v78; + else if (v70 < v78) + v70 = v78; + } + } + + float_t v79 = -v2; + if (v79 < v69) + v79 = v69; + if (v79 < -v68) + v79 = -v68; + if (v79 < v70) + v79 = v70; + + if (v79 > v67 + 1.2f) { + shadow_range = v67 + 2.4f; + separate = true; + } + else + shadow_range = v79 + 1.2f; + + if (vec3::dot(field_1A8[0] - interest_shared, direction) + < vec3::dot(field_1A8[1] - interest_shared, direction)) { + field_200[1] = 0; + field_200[0] = 1; + } + } + } + + for (prj::vector& i : field_1D0) + i.clear(); +} + +void Shadow::free() { + for (RenderTexture& i : render_textures) + i.Free(); + + reset(); +} float_t Shadow::get_shadow_range() { return shadow_range * shadow_range_factor; } +int32_t Shadow::init() { + struct shadow_texture_init_params { + int32_t width; + int32_t height; + int32_t max_level; + GLenum color_format; + GLenum depth_format; + } init_params[] = { + { 0x800, 0x800, 0, GL_RGBA8, GL_DEPTH_COMPONENT32F }, + { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { 0x200, 0x200, 3, GL_RGBA8, GL_ZERO }, + { 0x800, 0x800, 0, GL_R32F , GL_ZERO }, + { 0x800, 0x800, 0, GL_R32F , GL_ZERO }, + { 0x200, 0x200, 0, GL_R32F , GL_ZERO }, + { 0x200, 0x200, 0, GL_R32F , GL_ZERO }, + }; + + shadow_texture_init_params* v3 = init_params; + for (int32_t i = 0; i < 7; i++, v3++) + if (render_textures[i].Init(v3->width, v3->height, + v3->max_level, v3->color_format, v3->depth_format) < 0) + return -1; + + for (int32_t i = 0; i < 3; i++) { + gl_state_bind_texture_2d(render_textures[i].GetColorTex()); + glTexParameteriDLL(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); + glTexParameteriDLL(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); + static const vec4 border_color = 1.0f; + glTexParameterfvDLL(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, (GLfloat*)&border_color); + } + gl_state_bind_texture_2d(0); + gl_state_get_error(); + return 0; +} + +void Shadow::reset() { + shadow_range = 1.2f; + shadow_range_factor = 1.0f; + + for (int32_t i = 0; i < 2; i++) { + view_point[i] = 1.0f; + field_1C0[i] = 0.0f; + field_1C8[i] = 0.0f; + field_200[i] = i; + } + + for (RenderTexture*& i : curr_render_textures) + i = 0; + + view_mat[0] = mat4_identity; + view_mat[1] = mat4_identity; + blur_filter = BLUR_FILTER_9; + near_blur = 1; + field_2BC = 2; + far_blur = 1; + distance = 4.0f; + field_2C4 = 0.4f; + z_near = 0.1f; + z_far = 20.0f; + field_2D0 = 1.4f; + field_2D4 = 10000.0f; + field_2D8 = 80.0f; + field_2DC = 2.0f; + field_2E0 = 0.05f; + shadow_ambient = 0.4f; + num_light = 0; + direction = vec3(0.0f, -1.0f, -1.0f) * (1.0f / sqrtf(2.0f)); + show_texture = false; + self_shadow = true; + separate = false; + field_208 = (z_far - z_near) * 0.5f; +} + Shadow* shadow_ptr_get() { - return *shadow_ptr; + return shadow_ptr; +} + +HOOK(void, FASTCALL, shadow_ctrl, 0x0000000140502390) { + shadow_ptr_get()->ctrl(); +} + +HOOK(void, FASTCALL, Shadow__free, 0x00000001405E8350, Shadow* This) { + This->free(); +} + +void shadow_patch() { + INSTALL_HOOK(shadow_ctrl); + INSTALL_HOOK(Shadow__free); } diff --git a/src/DivaGL/shadow.hpp b/src/DivaGL/shadow.hpp index 5f3d9ed..aceb786 100644 --- a/src/DivaGL/shadow.hpp +++ b/src/DivaGL/shadow.hpp @@ -57,11 +57,19 @@ struct Shadow { bool blur_filter_enable[2]; bool separate; + void ctrl(); + void free(); float_t get_shadow_range(); + int32_t init(); + void reset(); }; static_assert(sizeof(Shadow) == 0x2F8, "\"Shadow\" struct should have a size of 0x2F8"); extern void(FASTCALL* sub_1405E8A20)(Shadow* shad, int32_t index, vec3* pos); +extern void(FASTCALL* shadow_ptr_free)(); +extern void(FASTCALL* shadow_ptr_init)(); extern Shadow* shadow_ptr_get(); + +extern void shadow_patch();