From b18198e65589f9ade57ecd309e43b2cfa221c313 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Tue, 21 Mar 2023 20:40:29 -0400 Subject: [PATCH] [jak2] fix atest flag in tfrag (#2381) Support the weird `tfrag-gs-test` and `texture-page-flag` stuff added in jak 2. Solves some issues with partially invisible tfrags. --- common/custom_data/Tfrag3Data.h | 2 +- decompiler/level_extractor/BspHeader.cpp | 5 +++ decompiler/level_extractor/BspHeader.h | 3 ++ decompiler/level_extractor/extract_level.cpp | 8 +++- decompiler/level_extractor/extract_tfrag.cpp | 39 ++++++++++++++------ decompiler/level_extractor/extract_tfrag.h | 3 +- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/common/custom_data/Tfrag3Data.h b/common/custom_data/Tfrag3Data.h index c66c51dd24..b8ade5e1f0 100644 --- a/common/custom_data/Tfrag3Data.h +++ b/common/custom_data/Tfrag3Data.h @@ -73,7 +73,7 @@ struct MemoryUsageTracker { void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; } }; -constexpr int TFRAG3_VERSION = 29; +constexpr int TFRAG3_VERSION = 30; // These vertices should be uploaded to the GPU at load time and don't change struct PreloadedVertex { diff --git a/decompiler/level_extractor/BspHeader.cpp b/decompiler/level_extractor/BspHeader.cpp index 3c4b209202..118e8600b0 100644 --- a/decompiler/level_extractor/BspHeader.cpp +++ b/decompiler/level_extractor/BspHeader.cpp @@ -1942,6 +1942,11 @@ void BspHeader::read_from_file(const decompiler::LinkedObjectFile& file, texture_remap_table.push_back(remap); } } + + if (version > GameVersion::Jak1) { + auto ff = get_field_ref(ref, "texture-flags", dts); + memcpy_plain_data((u8*)texture_flags, ff, sizeof(u16) * kNumTextureFlags); + } } std::string BspHeader::print(const PrintSettings& settings) const { diff --git a/decompiler/level_extractor/BspHeader.h b/decompiler/level_extractor/BspHeader.h index 7ebb55dba3..40dd0ad110 100644 --- a/decompiler/level_extractor/BspHeader.h +++ b/decompiler/level_extractor/BspHeader.h @@ -827,6 +827,9 @@ struct BspHeader { // (texture-remap-table (pointer uint64) :offset-assert 52) // (texture-remap-table-len int32 :offset-assert 56) std::vector texture_remap_table; + + static constexpr int kNumTextureFlags = 10; + u16 texture_flags[kNumTextureFlags]; // jak 2 only // // (texture-ids (pointer texture-id) :offset-assert 60) // (texture-page-count int32 :offset-assert 64) diff --git a/decompiler/level_extractor/extract_level.cpp b/decompiler/level_extractor/extract_level.cpp index c75cbefc5c..20a8943625 100644 --- a/decompiler/level_extractor/extract_level.cpp +++ b/decompiler/level_extractor/extract_level.cpp @@ -178,9 +178,15 @@ std::vector extract_bsp_from_level(const ObjectFileDB if (it != hacks.missing_textures_by_level.end()) { expected_missing_textures = it->second; } + bool atest_disable_flag = false; + if (db.version() == GameVersion::Jak2) { + if (bsp_header.texture_flags[0] & 1) { + atest_disable_flag = true; + } + } extract_tfrag(as_tfrag_tree, fmt::format("{}-{}", dgo_name, i++), bsp_header.texture_remap_table, tex_db, expected_missing_textures, level_data, - false, level_name); + false, level_name, atest_disable_flag); } else if (draw_tree->my_type() == "drawable-tree-instance-tie") { auto as_tie_tree = dynamic_cast(draw_tree.get()); ASSERT(as_tie_tree); diff --git a/decompiler/level_extractor/extract_tfrag.cpp b/decompiler/level_extractor/extract_tfrag.cpp index 456d6060f8..18d3f41c75 100644 --- a/decompiler/level_extractor/extract_tfrag.cpp +++ b/decompiler/level_extractor/extract_tfrag.cpp @@ -1825,7 +1825,8 @@ u32 remap_texture(u32 original, const std::vector& ma void process_draw_mode(std::vector& all_draws, const std::vector& map, - tfrag3::TFragmentTreeKind tree_kind) { + tfrag3::TFragmentTreeKind tree_kind, + bool disable_atest_for_normal_tfrag) { // set up the draw mode based on the code in background.gc and tfrag-methods.gc DrawMode mode; mode.set_alpha_test(DrawMode::AlphaTest::GEQUAL); @@ -1838,13 +1839,24 @@ void process_draw_mode(std::vector& all_draws, switch (tree_kind) { case tfrag3::TFragmentTreeKind::NORMAL: case tfrag3::TFragmentTreeKind::LOWRES: - mode.enable_at(); // :ate #x1 - mode.set_alpha_test(DrawMode::AlphaTest::GEQUAL); // :atst (gs-atest greater-equal) - mode.set_aref(0x26); // :aref #x26 - mode.set_alpha_fail(GsTest::AlphaFail::KEEP); - mode.enable_zt(); // :zte #x1 - mode.set_depth_test(GsTest::ZTest::GEQUAL); // :ztst (gs-ztest greater-equal)) - mode.disable_ab(); + if (disable_atest_for_normal_tfrag) { + mode.enable_at(); // :ate #x1 + mode.set_alpha_test(DrawMode::AlphaTest::ALWAYS); // :atst (gs-atest greater-equal) + mode.set_aref(0x0); // :aref #x26 + mode.set_alpha_fail(GsTest::AlphaFail::KEEP); + mode.enable_zt(); // :zte #x1 + mode.set_depth_test(GsTest::ZTest::GEQUAL); // :ztst (gs-ztest greater-equal)) + mode.disable_ab(); + } else { + mode.enable_at(); // :ate #x1 + mode.set_alpha_test(DrawMode::AlphaTest::GEQUAL); // :atst (gs-atest greater-equal) + mode.set_aref(0x26); // :aref #x26 + mode.set_alpha_fail(GsTest::AlphaFail::KEEP); + mode.enable_zt(); // :zte #x1 + mode.set_depth_test(GsTest::ZTest::GEQUAL); // :ztst (gs-ztest greater-equal)) + mode.disable_ab(); + } + break; case tfrag3::TFragmentTreeKind::TRANS: case tfrag3::TFragmentTreeKind::LOWRES_TRANS: @@ -2097,7 +2109,8 @@ void emulate_tfrags(int geom, const TextureDB& tdb, const std::vector>& expected_missing_textures, bool dump_level, - const std::string& level_name) { + const std::string& level_name, + bool disable_alpha_test_in_normal) { TFragExtractStats stats; std::vector vu_mem; @@ -2113,7 +2126,7 @@ void emulate_tfrags(int geom, all_draws.insert(all_draws.end(), draws.begin(), draws.end()); } - process_draw_mode(all_draws, map, tree_out.kind); + process_draw_mode(all_draws, map, tree_out.kind, disable_alpha_test_in_normal); auto groups = make_draw_groups(all_draws); make_tfrag3_data(groups, tree_out, vertices, level_out.textures, tdb, expected_missing_textures, @@ -2160,7 +2173,8 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree, const std::vector>& expected_missing_textures, tfrag3::Level& out, bool dump_level, - const std::string& level_name) { + const std::string& level_name, + bool disable_atest_in_normal) { // go through 3 lods(?) for (int geom = 0; geom < GEOM_MAX; ++geom) { tfrag3::TfragTree this_tree; @@ -2223,7 +2237,8 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree, std::vector vertices; emulate_tfrags(geom, as_tfrag_array->tfragments, debug_name, map, out, this_tree, vertices, - tex_db, expected_missing_textures, dump_level, level_name); + tex_db, expected_missing_textures, dump_level, level_name, + disable_atest_in_normal); pack_tfrag_vertices(&this_tree.packed_vertices, vertices); extract_time_of_day(tree, this_tree); diff --git a/decompiler/level_extractor/extract_tfrag.h b/decompiler/level_extractor/extract_tfrag.h index 8f1aaf35d2..78917b55ea 100644 --- a/decompiler/level_extractor/extract_tfrag.h +++ b/decompiler/level_extractor/extract_tfrag.h @@ -29,6 +29,7 @@ void extract_tfrag(const level_tools::DrawableTreeTfrag* tree, const std::vector>& expected_missing_textures, tfrag3::Level& out, bool dump_level, - const std::string& level_name); + const std::string& level_name, + bool disable_atest_in_normal); } // namespace decompiler