From 1487d54c08907f5600aa739947db1580be44fbd1 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Fri, 1 Nov 2024 00:15:08 -0400 Subject: [PATCH] feat(zelda-eow): first commit --- CMakeLists.txt | 18 ++ src/games/zelda-eow/0xA380E737.frag.glsl | 379 +++++++++++++++++++++++ src/games/zelda-eow/0xA380E737.frag.spv | Bin 0 -> 27148 bytes src/games/zelda-eow/0xF3C7B934.frag.glsl | 44 +++ src/games/zelda-eow/0xF3C7B934.frag.spv | Bin 0 -> 4728 bytes src/games/zelda-eow/addon.cpp | 45 +++ 6 files changed, 486 insertions(+) create mode 100644 src/games/zelda-eow/0xA380E737.frag.glsl create mode 100644 src/games/zelda-eow/0xA380E737.frag.spv create mode 100644 src/games/zelda-eow/0xF3C7B934.frag.glsl create mode 100644 src/games/zelda-eow/0xF3C7B934.frag.spv create mode 100644 src/games/zelda-eow/addon.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d32d9469..cddfdf4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,24 @@ function(build_shader_target ADDON ADDON_PATH) list(APPEND SHADER_HEADER_FILES ${EMBED_FOLDER}/${SHADER_HASH}.h) endif() endforeach() + + file(GLOB SHADER_BINARIES ${ADDON_PATH}/*.spv) + foreach(FILE ${SHADER_BINARIES}) + cmake_path(GET FILE FILENAME FILENAME) + cmake_path(GET FILE PARENT_PATH TARGET_PATH) + string(REGEX MATCH "(0x[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F])(\\.(frag|vert))?\\.spv$" _ ${FILENAME} ) + set(SHADER_HASH ${CMAKE_MATCH_1}) + SET(EMBED_FOLDER ${CMAKE_CURRENT_BINARY_DIR}/${ADDON}.include/embed) + + if (SHADER_HASH) + add_custom_command( + OUTPUT ${EMBED_FOLDER}/${SHADER_HASH}.h + COMMAND embedfile ${FILE} ${EMBED_FOLDER}/${SHADER_HASH} + DEPENDS ${FILE} + ) + list(APPEND SHADER_HEADER_FILES ${EMBED_FOLDER}/${SHADER_HASH}.h) + endif() + endforeach() LIST(JOIN SHADER_HEADER_FILES " " SHADER_HEADER_FILE_ITEMS) add_custom_target(${ADDON}-shaders DEPENDS ${SHADER_HEADER_FILES}) diff --git a/src/games/zelda-eow/0xA380E737.frag.glsl b/src/games/zelda-eow/0xA380E737.frag.glsl new file mode 100644 index 00000000..3db99934 --- /dev/null +++ b/src/games/zelda-eow/0xA380E737.frag.glsl @@ -0,0 +1,379 @@ +// Tonemapper + +#version 450 + +layout(set = 0, binding = 0, std140) uniform support_buffer { + uint _m0; + uint _m1[8]; + vec4 _m2; + vec4 _m3; + int _m4; + float _m5[73]; + ivec4 _m6; + int _m7; +} +support_buffer_1; + +layout(set = 0, binding = 22, std140) uniform fp_c3 { vec4 _m0[4096]; } +fp_c3_1; + +layout(set = 0, binding = 25, std140) uniform fp_c6 { vec4 _m0[4096]; } +fp_c6_1; + +layout(set = 0, binding = 24, std140) uniform fp_c5 { vec4 _m0[4096]; } +fp_c5_1; + +layout(set = 0, binding = 20, std140) uniform fp_c1 { vec4 _m0[4096]; } +fp_c1_1; + +layout(set = 2, binding = 128) uniform sampler2D fp_t_tcb_8; + +layout(location = 0) noperspective in vec4 _33; +layout(location = 0) out vec4 _36; + +vec3 ReinhardScalable(vec3 color, vec3 channel_max, vec3 channel_min, + vec3 gray_in, vec3 gray_out) { + vec3 exposure = + (channel_max * (channel_min * gray_out + channel_min - gray_out)) / + (gray_in * (gray_out - channel_max)); + return fma(color.rgb, exposure, channel_min) / + fma(color, exposure / channel_max, 1.f - channel_min); +} + +const mat3 BT709_TO_XYZ_MAT = mat3(0.4123907993f, 0.3575843394f, 0.1804807884f, + 0.2126390059f, 0.7151686788f, 0.0721923154f, + 0.0193308187f, 0.1191947798f, 0.9505321522f); + +const mat3 XYZ_TO_BT709_MAT = mat3( + 3.2409699419f, -1.5373831776f, -0.4986107603f, -0.9692436363f, + 1.8759675015f, 0.0415550574f, 0.0556300797f, -0.2039769589f, 1.0569715142f); + +const mat3 XYZ_TO_LMS_MAT = + mat3(0.3592832590121217f, 0.6976051147779502f, -0.0358915932320290f, + -0.1920808463704993f, 1.1004767970374321f, 0.0753748658519118f, + 0.0070797844607479f, 0.0748396662186362f, 0.8433265453898765f); + +const mat3 LMS_TO_XYZ_MAT = + mat3(2.07018005669561320, -1.32645687610302100, 0.206616006847855170, + 0.36498825003265756, 0.68046736285223520, -0.045421753075853236, + -0.04959554223893212, -0.04942116118675749, 1.187995941732803400); + +const float PEAK_NITS = 800.f; +const float GAME_NITS = 203.f; +const float UI_NITS = 203.f; + +float HejlDawsonCustom(float color, float a, float b) { + color = max(0, color - 0.004f); + color = (color * (a * color + 0.5f)) / (color * (a * color + 1.7f) + b); + return pow(color, 2.2f); +} + +float HejlDawson(float color, float a, float b) { + return HejlDawsonCustom(color, 6.2f, 0.06f); +} + +vec3 EncodePQ(vec3 color, float scaling) { + float M1 = 2610.f / 16384.f; // 0.1593017578125f; + float M2 = 128.f * (2523.f / 4096.f); // 78.84375f; + float C1 = 3424.f / 4096.f; // 0.8359375f; + float C2 = 32.f * (2413.f / 4096.f); // 18.8515625f; + float C3 = 32.f * (2392.f / 4096.f); // 18.6875f; + color *= (scaling / 10000.f); + vec3 y_m1 = pow(color, vec3(M1)); + return pow((vec3(C1) + vec3(C2) * y_m1) / (1.f + vec3(C3) * y_m1), vec3(M2)); +} +vec3 EncodePQ(vec3 color) { return EncodePQ(color, 10000.f); } + +vec3 DecodePQ(vec3 in_color, float scaling) { + float M1 = 2610.f / 16384.f; // 0.1593017578125f; + float M2 = 128.f * (2523.f / 4096.f); // 78.84375f; + float C1 = 3424.f / 4096.f; // 0.8359375f; + float C2 = 32.f * (2413.f / 4096.f); // 18.8515625f; + float C3 = 32.f * (2392.f / 4096.f); // 18.6875f; + + vec3 e_m12 = pow(in_color, 1.f / vec3(M2)); + vec3 out_color = pow(max(e_m12 - vec3(C1), 0) / (vec3(C2) - vec3(C3) * e_m12), + 1.f / vec3(M1)); + return out_color * (10000.f / scaling); +} +vec3 DecodePQ(vec3 color) { return DecodePQ(color, 10000.f); } + +vec3 IctcpFromBT709(vec3 bt709_color) { + vec3 xyz_color = bt709_color * BT709_TO_XYZ_MAT; + vec3 lms_color = xyz_color * XYZ_TO_LMS_MAT; + + mat3 mat = mat3(0.5000, 0.5000, 0.0000, 1.6137, -3.3234, 1.7097, 4.3780, + -4.2455, -0.1325); + + return EncodePQ(lms_color, 100.0f) * mat; +} + +vec3 BT709FromICtCp(vec3 col) { + mat3 mat = mat3(1.0, 0.00860514569398152, 0.11103560447547328, 1.0, + -0.00860514569398152, -0.11103560447547328, 1.0, + 0.56004885956263900, -0.32063747023212210); + col = col * mat; + + // 1.0f = 100 nits, 100.0f = 10k nits + col = DecodePQ(col, 100.f); + col = col * LMS_TO_XYZ_MAT; + return col * XYZ_TO_BT709_MAT; +} + +float EncodeSRGB(float channel) { + return (channel <= 0.0031308f) ? (channel * 12.92f) + : (1.055f * pow(channel, 1.f / 2.4f) - 0.055f); +} + +float DecodeSRGB(float channel) { + return (channel <= 0.04045f) ? (channel / 12.92f) + : pow((channel + 0.055f) / 1.055f, 2.4f); +} + +vec3 renodrt(vec3 bt709, float nits_peak, float mid_gray_value, + float mid_gray_nits, float exposure, float highlights, + float shadows, float contrast, float saturation, float dechroma, + float flare, float hue_correction_strength, + vec3 hue_correction_source) { + const float n_r = 100.f; + float n = 1000.f; + + // drt cam + // n_r = 100 + // g = 1.15 + // c = 0.18 + // c_d = 10.013 + // w_g = 0.14 + // t_1 = 0.04 + // r_hit_min = 128 + // r_hit_max = 896 + + float g = 1.1; // gamma/contrast + float c = 0.18; // scene-referred gray + float c_d = 10.013; // output gray in nits + const float w_g = 0.00f; // gray change + float t_1 = 0.01; // shadow toe + const float r_hit_min = 128; + const float r_hit_max = 256; + + g = contrast; + c = mid_gray_value; + c_d = mid_gray_nits; + n = nits_peak; + t_1 = flare; + + vec3 signs = sign(bt709); + + bt709 = abs(bt709); + + float y_original = + dot(bt709, vec3(0.2126390059f, 0.7151686788f, 0.0721923154f)); + + vec3 perceptual_old = IctcpFromBT709(hue_correction_source); + + float y = y_original * exposure; + + float y_normalized = y / 0.18f; + + float y_highlighted = pow(y_normalized, highlights); + y_highlighted = mix(y_normalized, y_highlighted, clamp(y_normalized, 0, 1.f)); + + float y_shadowed = pow(y_highlighted, -1.f * (shadows - 2.f)); + y_shadowed = mix(y_shadowed, y_highlighted, clamp(y_highlighted, 0, 1.f)); + y_shadowed *= 0.18f; + y = y_shadowed; + + float m_0 = (n / n_r); + float ts; + float m_1 = 0.5 * (m_0 + sqrt(m_0 * (m_0 + (4.0 * t_1)))); + float r_hit = + r_hit_min + ((r_hit_max - r_hit_min) * (log(m_0) / log(10000.0 / 100.0))); + + float u = pow((r_hit / m_1) / ((r_hit / m_1) + 1.0), g); + const float m = m_1 / u; + const float w_i = log(n / 100.0) / log(2.0); + const float c_t = (c_d / n_r) * (1.0 + (w_i * w_g)); + const float g_ip = 0.5 * (c_t + sqrt(c_t * (c_t + (4.0 * t_1)))); + const float g_ipp2 = + -m_1 * pow(g_ip / m, 1.0 / g) / (pow(g_ip / m, 1.0 / g) - 1.0); + const float w_2 = c / g_ipp2; + const float s_2 = w_2 * m_1; + float u_2 = pow((r_hit / m_1) / ((r_hit / m_1) + w_2), g); + float m_2 = m_1 / u_2; + + ts = pow(max(0, y) / (y + s_2), g) * m_2; + + float flared = max(0, (ts * ts) / (ts + t_1)); + + float y_new = clamp(flared, 0, m_0); + + vec3 color_output = + signs * bt709 * (y_original > 0 ? (y_new / y_original) : 0); + vec3 color = color_output; + + if (dechroma != 0.f || saturation != 1.f || hue_correction_strength != 0.f) { + vec3 perceptual_new = IctcpFromBT709(color_output); + + if (hue_correction_strength != 0.f) { + // Save chrominance to apply black + float chrominance_pre_adjust = distance(perceptual_new.yz, vec2(0)); + + perceptual_new.yz = + mix(perceptual_new.yz, perceptual_old.yz, hue_correction_strength); + + float chrominance_post_adjust = distance(perceptual_new.yz, vec2(0)); + + // Apply back previous chrominance + if (chrominance_post_adjust != 0.f) { + perceptual_new.yz *= chrominance_pre_adjust / chrominance_post_adjust; + } + } + + if (dechroma != 0.f) { + perceptual_new.yz *= mix( + 1.f, 0.f, + clamp(pow(y_original / (10000.f / 100.f), (1.f - dechroma)), 0, 1.f)); + } + + perceptual_new.yz *= saturation; + + color = BT709FromICtCp(perceptual_new); + + // color = renodx::color::bt709::clamp::AP1(color); + color = min(vec3(m_0), color); // Clamp to Peak + } + + return color; +} + +void main() { + float _43 = _33.x; + float _45 = _33.y; + vec4 _48 = textureLodOffset(fp_t_tcb_8, vec2(_43, _45), 0.0, ivec2(0)).xyzw; + float _50 = _48.x; + float _52 = _48.y; + float _54 = _48.z; + float _56 = _48.w; + precise float _217 = 1.0 / fp_c3_1._m0[0].z; + float _58 = _217; + float _60 = -fp_c3_1._m0[0].x; + precise float _223 = _43 + _60; + float _62 = _223; + precise float _227 = 1.0 / fp_c3_1._m0[0].w; + float _64 = _227; + float _66 = -fp_c3_1._m0[0].y; + precise float _233 = _45 + _66; + float _68 = _233; + float _70 = fma(_62, _58, fp_c6_1._m0[1].x); + float _72 = fma(_68, _64, fp_c6_1._m0[1].y); + precise float _247 = _70 + (-0.5); + float _74 = _247; + precise float _249 = _72 + (-0.5); + float _76 = _249; + precise float _252 = _74 * _74; + float _78 = _252; + precise float _256 = _76 * fp_c6_1._m0[0].w; + float _80 = _256; + float _82 = fma(_80, _80, _78); + float _84 = -fp_c6_1._m0[0].x; + float _86 = fma(_82, _84, fp_c6_1._m0[0].x); + float _88 = clamp(_86, 0.0, 1.0); + float _90 = log2(_88); + precise float _276 = _90 * fp_c6_1._m0[0].y; + float _92 = _276; + float _94 = exp2(_92); + precise float _282 = _94 + fp_c6_1._m0[0].z; + float _96 = _282; + float _98 = clamp(_96, 0.0, 1.0); + precise float _287 = _98 * _50; + float _100 = _287; + precise float _290 = _98 * _52; + float _102 = _290; + precise float _293 = _98 * _54; + float _104 = _293; + float _106 = fma(_100, fp_c5_1._m0[0].x, -0.0040000001899898052215576171875); + float _108 = fma(_102, fp_c5_1._m0[0].x, -0.0040000001899898052215576171875); + float _110 = fma(_104, fp_c5_1._m0[0].x, -0.0040000001899898052215576171875); + float _112 = max(0.0, _106); + float _114 = max(0.0, _110); + float _116 = max(0.0, _108); + float _118 = fma(_112, fp_c1_1._m0[0].x, 1.7000000476837158203125); + float _120 = fma(_114, fp_c1_1._m0[0].x, 1.7000000476837158203125); + float _122 = fma(_114, fp_c1_1._m0[0].x, 0.5); + float _124 = fma(_116, fp_c1_1._m0[0].x, 1.7000000476837158203125); + float _126 = fma(_112, fp_c1_1._m0[0].x, 0.5); + float _128 = fma(_112, _118, fp_c1_1._m0[0].y); + float _130 = fma(_116, fp_c1_1._m0[0].x, 0.5); + float _132 = fma(_114, _120, fp_c1_1._m0[0].y); + precise float _350 = 1.0 / _128; + float _134 = _350; + precise float _353 = _114 * _122; + float _136 = _353; + float _138 = fma(_116, _124, fp_c1_1._m0[0].y); + precise float _360 = 1.0 / _132; + float _140 = _360; + precise float _363 = _112 * _126; + float _142 = _363; + precise float _365 = 1.0 / _138; + float _144 = _365; + precise float _368 = _116 * _130; + float _146 = _368; + precise float _371 = _142 * _134; + float _148 = _371; + precise float _374 = _136 * _140; + float _150 = _374; + float _152 = abs(_148); + float _154 = log2(_152); + precise float _381 = _146 * _144; + float _156 = _381; + float _158 = abs(_150); + float _160 = log2(_158); + float _162 = abs(_156); + float _164 = log2(_162); + precise float _392 = _154 * 2.2000000476837158203125; + float _166 = _392; + precise float _394 = _160 * 2.2000000476837158203125; + float _168 = _394; + precise float _397 = _98 * _56; + float _170 = _397; + precise float _399 = _164 * 2.2000000476837158203125; + float _172 = _399; + float _174 = exp2(_166); + float _176 = clamp(_174, 0.0, 1.0); + precise float _407 = _170 * fp_c5_1._m0[0].x; + float _178 = _407; + float _180 = exp2(_168); + float _182 = clamp(_180, 0.0, 1.0); + float _184 = exp2(_172); + float _186 = clamp(_184, 0.0, 1.0); + _36.x = _176; + _36.y = _186; + _36.z = _182; + _36.w = _178; + + vec3 untonemapped = vec3(_100, _102, _104); + float vanilla_mid_gray = + HejlDawsonCustom(0.18f, fp_c1_1._m0[0].x, fp_c1_1._m0[0].y); // 0.225f + untonemapped *= fp_c5_1._m0[0].x; // 2x exposure + vec3 vanilla = + vec3(HejlDawsonCustom(_36.r, fp_c1_1._m0[0].x, fp_c1_1._m0[0].y), + HejlDawsonCustom(_36.g, fp_c1_1._m0[0].x, fp_c1_1._m0[0].y), + HejlDawsonCustom(_36.b, fp_c1_1._m0[0].x, fp_c1_1._m0[0].y)); + + float peak = PEAK_NITS / GAME_NITS; + peak = DecodeSRGB(pow(peak, 1.f / 2.2f)); + + _36.rgb = renodrt(untonemapped, peak * 100.f, 0.18f, vanilla_mid_gray * 100.f, + 1.0f, // float exposure, + 1.0f, // float highlights, + 1.1f, // float shadows, + 1.2f, // float contrast, + 1.6f, // float saturation, + 0.8, // float dechroma, + 0.25, // float flare, + 0.5f, // float hue_correction_strength, + vanilla.rgb); + // _36.rgb = vec3(vanilla_mid_gray * 1.f / 80.f); + // _36.rgb = ReinhardScalable(_36.rgb, (800.f / 203.f).xxx, (0).xxx, + // (0.18f).xxx, (0.18f).xxx); _36.w = 0; +} diff --git a/src/games/zelda-eow/0xA380E737.frag.spv b/src/games/zelda-eow/0xA380E737.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..0638031ab0aeb585e8f812f03306edf40f70eefd GIT binary patch literal 27148 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 literal 0 HcmV?d00001 diff --git a/src/games/zelda-eow/0xF3C7B934.frag.glsl b/src/games/zelda-eow/0xF3C7B934.frag.glsl new file mode 100644 index 00000000..746be18e --- /dev/null +++ b/src/games/zelda-eow/0xF3C7B934.frag.glsl @@ -0,0 +1,44 @@ +// Final output + +#version 450 + +layout(set = 2, binding = 0) uniform sampler2D tex; + +layout(location = 0) out vec4 colour; +layout(location = 0) in vec2 tex_coord; + +float encode_srgb(float channel) { + return (channel <= 0.0031308f) ? (channel * 12.92f) + : (1.055f * pow(channel, 1.f / 2.4f) - 0.055f); +} + +vec3 encode_srgb(vec3 color) { + return vec3(encode_srgb(color.r), encode_srgb(color.g), encode_srgb(color.b)); +} + +const mat3 BT709_TO_BT2020_MAT = + mat3(0.6274038959, 0.3292830384, 0.0433130657, 0.0690972894, 0.9195403951, + 0.0113623156, 0.0163914389, 0.0880133079, 0.8955952532); + +vec3 EncodePQ(vec3 color, float scaling) { + float M1 = 2610.f / 16384.f; // 0.1593017578125f; + float M2 = 128.f * (2523.f / 4096.f); // 78.84375f; + float C1 = 3424.f / 4096.f; // 0.8359375f; + float C2 = 32.f * (2413.f / 4096.f); // 18.8515625f; + float C3 = 32.f * (2392.f / 4096.f); // 18.6875f; + color *= (scaling / 10000.f); + vec3 y_m1 = pow(color, vec3(M1)); + return pow((vec3(C1) + vec3(C2) * y_m1) / (1.f + vec3(C3) * y_m1), vec3(M2)); +} + +void main() { + colour = vec4(texture(tex, tex_coord).xyz, 1.0); + vec3 signs = sign(colour.rgb); + colour.rgb = abs(colour.rgb); + colour.rgb = encode_srgb(colour.rgb); + colour.rgb = signs * pow(colour.rgb, vec3(2.2f)); + + colour.rgb = colour.rgb * BT709_TO_BT2020_MAT; + colour.rgb = max(colour.rgb, vec3(0)); + colour.rgb = EncodePQ(colour.rgb, 203.f); +} diff --git a/src/games/zelda-eow/0xF3C7B934.frag.spv b/src/games/zelda-eow/0xF3C7B934.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..3b27418fb28e5b585ce31da6864e71046342ca1a GIT binary patch literal 4728 zcmZ9NXLD9n6oqe0AaqoUfGCMrV8kfW#1Io|kS3sj9b$+f0*Mmr4MmE*A~x&=3y2*% zD0ZFki$B0$VVTkKdET5IuJ_FBIcu%6_C9Byd*Az(A2GTz%gVC8S+DHptZN*V9f6Xe z^(@Ve3(j9q)46eV&BRG(=opZdmyCJ_W|dh5v$4LZt=)w-;u_*eeClifDyM3eeMM3a z)V#k3`}AS0rMj;!ttJ?Jew{iK|B*YGwHL%NpBQS=sNcz@Qo|iD{w$}E}#J4f$&wjAL59N3xPs06F)b-g`AN)l4vSq)W6Z{nT-o~c7A=Et$Ttzrsm)Dfo zVa{VL{Z3;2EV%a&^%}rg)#&c}Gvxbr&4~3`@@#qcdFDueeZ2d;bLE?Mbn|)ghLLk3 z|6+NzsouM61$h@0gm<}y*?U#5P2A_LHazQ{UB#@wjL47R$KqVef5z=UUWx1^oM+_tyn~6`r-O?XLS8v~29z)1uC9 zxH>3;qUtX~X;7b>D=4I=iJl>bwOvN1toz&ol2KJgfWYiFzM_9g)8u ztQHZz187+`f97OSjVgj$^G=A@}R;!OS0J9$geJfB``dUxtk^Hy-a=525_!%?hx zd(wP9dZ*L>CgwW`>-gP?Uhf3!ceuA6waD2FHpg#M*agB53bi?9X)E1b3fRe ze6J6{&2fKo^r%J7gJ5&=y*>mtCwkSRX0M+2VZvt|y*~oBM!YkRg4GO1^xltm(fr4g zHiB8N-?c62E_Q;guP4s<1h{w?Pon8{*q0u)$axA}yo;yN%!#|uqZT>OfQxsr3(cIk z3q5Ml`?KJD@6W;23`g|-Q0i|lnw~vG?E5yj*xx=hy$<`+qZT>ufQ$XTi)K#rr$;Sv z-UAo=dmqi5=ueMY^!EWc-`|IDHNz48#k2i5X=9l6?k8gZPr$`KKSeXgVV`=`BIh%3 zvCq%ZVjpw#s71~fDJTCrwlMDrXV? zANGXzAsoGkDb%iH?oIgL*q7P=Mzv!JXYbCuV+ehpQD->wh@=f;{)0NlF+2Xo@7hSB zny{`o>KqTYj^6_7RuO8W2zzzkD&jBltZBY=B7Zd4eBVX$Pa?_)_jK(EykbKlr+EZ8&s%Q?hxmww}pBpd?>@3KGhK*BR0#T<7z4(we9KeNE6 zB<}OocRFF68Y0edM$$dA_2mAycn9MNpR0P*mmcK`TOOB(7xW_>Wdmn=d?{p}0 z++jU9f2Y$6d}e{qF7U=2_qi=f+`g>cK!~k7BVlXKO4xdH61LV{BJSv1uxH+$p3i)+ z+B`y!_p*Sn#|QAp7bZ=w`?{tU{`0_UvBzSt=Zt$^Qo{1Ch;Q{$c>F%Bq0jpE>sr)1 zA8db7?*gz|MEI7W*?ahwgViG9yerV$BmVO*1nX75BlUa{*nM1!`j>#c&!~SXSS=#z zUxt>ie>q&QdgQJIU!05BcNLmz=J<@f|0crotRmtpSAc!~QLh=S77=&68ZGYFI{JLi I)qT(Z0|ZNn-v9sr literal 0 HcmV?d00001 diff --git a/src/games/zelda-eow/addon.cpp b/src/games/zelda-eow/addon.cpp new file mode 100644 index 00000000..62d2e617 --- /dev/null +++ b/src/games/zelda-eow/addon.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Carlos Lopez + * SPDX-License-Identifier: MIT + */ + +#define ImTextureID ImU64 + +#define DEBUG_LEVEL_0 + +#include +#include + +#include +#include + +#include "../../mods/shader.hpp" + +namespace { + +renodx::mods::shader::CustomShaders custom_shaders = { + CustomShaderEntry(0xA380E737), + CustomShaderEntry(0xF3C7B934), +}; + +} // namespace + +extern "C" __declspec(dllexport) constexpr const char* NAME = "RenoDX"; +extern "C" __declspec(dllexport) constexpr const char* DESCRIPTION = "RenoDX for Zelda : Echoes of Wisdom"; + +BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) { + switch (fdw_reason) { + case DLL_PROCESS_ATTACH: + if (!reshade::register_addon(h_module)) return FALSE; + + break; + case DLL_PROCESS_DETACH: + + reshade::unregister_addon(h_module); + break; + } + + renodx::mods::shader::Use(fdw_reason, custom_shaders); + + return TRUE; +}