diff --git a/decompiler/ObjectFile/ObjectFileDB.cpp b/decompiler/ObjectFile/ObjectFileDB.cpp index 14034685d6..393cb113f5 100644 --- a/decompiler/ObjectFile/ObjectFileDB.cpp +++ b/decompiler/ObjectFile/ObjectFileDB.cpp @@ -120,6 +120,7 @@ ObjectFileDB::ObjectFileDB(const std::vector& _dgos, const std::vector& object_files, const std::vector& str_files, const std::vector& str_tex_files, + const std::vector& str_art_files, const Config& config) : dts(config.game_version), m_version(config.game_version) { Timer timer; @@ -237,6 +238,18 @@ ObjectFileDB::ObjectFileDB(const std::vector& _dgos, } } + if (!str_art_files.empty()) { + lg::info("-Loading {} streaming art files...", str_art_files.size()); + for (auto& obj : str_art_files) { + StrFileReader reader(obj, version()); + for (int i = 0; i < reader.chunk_count(); i++) { + auto name = reader.get_chunk_art_name(i); + add_obj_from_dgo(name, name, reader.get_chunk(i).data(), reader.get_chunk(i).size(), + "ARTSPOOL", config, name); + } + } + } + lg::info("ObjectFileDB Initialized"); if (obj_files_by_name.empty()) { lg::error( diff --git a/decompiler/ObjectFile/ObjectFileDB.h b/decompiler/ObjectFile/ObjectFileDB.h index 38d922a3ab..0811bafb3c 100644 --- a/decompiler/ObjectFile/ObjectFileDB.h +++ b/decompiler/ObjectFile/ObjectFileDB.h @@ -169,6 +169,7 @@ class ObjectFileDB { const std::vector& object_files, const std::vector& str_files, const std::vector& str_tex_files, + const std::vector& str_art_files, const Config& config); std::string generate_dgo_listing(); std::string generate_obj_listing(const std::unordered_set& merged_objs); diff --git a/decompiler/config.cpp b/decompiler/config.cpp index c15cd1c6fe..984b1f564a 100644 --- a/decompiler/config.cpp +++ b/decompiler/config.cpp @@ -59,6 +59,11 @@ Config make_config_via_json(nlohmann::json& json) { inputs_json.at("str_texture_file_names").get>(); } + if (inputs_json.contains("str_art_file_names")) { + config.str_art_file_names = + inputs_json.at("str_art_file_names").get>(); + } + config.audio_dir_file_name = inputs_json.at("audio_dir_file_name").get(); config.streamed_audio_file_names = inputs_json.at("streamed_audio_file_names").get>(); diff --git a/decompiler/config.h b/decompiler/config.h index 16ce685523..01ddca559a 100644 --- a/decompiler/config.h +++ b/decompiler/config.h @@ -101,6 +101,7 @@ struct Config { std::vector object_file_names; std::vector str_file_names; std::vector str_texture_file_names; + std::vector str_art_file_names; std::string audio_dir_file_name; std::vector streamed_audio_file_names; diff --git a/decompiler/config/jak3/jak3_config.jsonc b/decompiler/config/jak3/jak3_config.jsonc index 4d0c698c51..e08a587273 100644 --- a/decompiler/config/jak3/jak3_config.jsonc +++ b/decompiler/config/jak3/jak3_config.jsonc @@ -109,7 +109,7 @@ // optional: a predetermined object file name map from a file. // this will make decompilation naming consistent even if you only run on some objects. - "obj_file_name_map_file": "goal_src/jak3/build/all_objs.json", + // "obj_file_name_map_file": "goal_src/jak3/build/all_objs.json", //////////////////////////// // LEVEL EXTRACTION diff --git a/decompiler/config/jak3/ntsc_v1/inputs.jsonc b/decompiler/config/jak3/ntsc_v1/inputs.jsonc index 5246f6628b..cf55ccbbb8 100644 --- a/decompiler/config/jak3/ntsc_v1/inputs.jsonc +++ b/decompiler/config/jak3/ntsc_v1/inputs.jsonc @@ -290,6 +290,11 @@ // some objects are part of STR files (streaming data). "str_file_names": [], + // streaming "art" that should be added to GAME.FR3. + "str_art_file_names": [ + "STR/JAEXTERN.STR" + ], + // some objects are directly stored as files on the DVD. This is just text files. "object_file_names": [ "TEXT/0COMMON.TXT", diff --git a/decompiler/data/StrFileReader.cpp b/decompiler/data/StrFileReader.cpp index e573be4c6b..016e809a34 100644 --- a/decompiler/data/StrFileReader.cpp +++ b/decompiler/data/StrFileReader.cpp @@ -188,6 +188,21 @@ FullName extract_name(const std::string& file_info_name) { } // namespace +std::string StrFileReader::get_chunk_art_name(int idx) const { + const auto& file_info_string = get_art_group_file_info_string(); + const auto& chunk = m_chunks.at(idx); + int offset; + if (find_string_in_data(chunk.data(), int(chunk.size()), file_info_string, &offset)) { + offset += file_info_string.length(); + } else { + ASSERT_MSG(false, fmt::format("did not find string '{}'", file_info_string)); + } + + // extract the name info as a "name" + "chunk id" + "-ag.go" format. + return extract_name(get_string_of_max_length((const char*)(chunk.data() + offset), 128)).name + + "-ag"; +} + /*! * Look inside the chunks to determine the source file name. * Does a lot of checking, might not work in future versions without some updating. diff --git a/decompiler/data/StrFileReader.h b/decompiler/data/StrFileReader.h index 496501748d..a3120828b8 100644 --- a/decompiler/data/StrFileReader.h +++ b/decompiler/data/StrFileReader.h @@ -19,6 +19,8 @@ class StrFileReader { explicit StrFileReader(const fs::path& file_path, GameVersion version); int chunk_count() const; const std::vector& get_chunk(int idx) const; + std::string get_chunk_art_name(int idx) const; + std::string get_full_name(const std::string& short_name) const; std::string get_texture_name() const; diff --git a/decompiler/extractor/main.cpp b/decompiler/extractor/main.cpp index f37cec6a0b..cbb31c45b0 100644 --- a/decompiler/extractor/main.cpp +++ b/decompiler/extractor/main.cpp @@ -113,7 +113,7 @@ void decompile(const fs::path& iso_data_path, const std::string& data_subfolder) fmt::format("{}_config.jsonc", version_info.game_name), version_info.decomp_config_version); - std::vector dgos, objs, tex_strs; + std::vector dgos, objs, tex_strs, art_strs; // grab all DGOS we need (level + common) // TODO - Jak 2 - jak 1 specific code? @@ -141,8 +141,13 @@ void decompile(const fs::path& iso_data_path, const std::string& data_subfolder) tex_strs.push_back(iso_data_path / str_name); } + for (const auto& str_name : config.str_art_file_names) { + art_strs.push_back(iso_data_path / str_name); + } + // set up objects - ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, tex_strs, config); + ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, tex_strs, art_strs, + config); // save object files auto out_folder = file_util::get_jak_project_dir() / "decompiler_out" / data_subfolder; diff --git a/decompiler/level_extractor/extract_level.cpp b/decompiler/level_extractor/extract_level.cpp index 191f1a2d3f..e887c9661b 100644 --- a/decompiler/level_extractor/extract_level.cpp +++ b/decompiler/level_extractor/extract_level.cpp @@ -92,7 +92,6 @@ tfrag3::Texture make_texture(u32 id, void add_all_textures_from_level(tfrag3::Level& lev, const std::string& level_name, const TextureDB& tex_db) { - ASSERT(lev.textures.empty()); const auto& level_it = tex_db.texture_ids_per_level.find(level_name); if (level_it != tex_db.texture_ids_per_level.end()) { for (auto id : level_it->second) { @@ -125,12 +124,14 @@ void extract_art_groups_from_level(const ObjectFileDB& db, const std::string& dgo_name, tfrag3::Level& level_data, std::map& art_group_data) { - const auto& files = db.obj_files_by_dgo.at(dgo_name); - for (const auto& file : files) { - if (file.name.length() > 3 && !file.name.compare(file.name.length() - 3, 3, "-ag")) { - const auto& ag_file = db.lookup_record(file); - extract_merc(ag_file, tex_db, db.dts, tex_remap, level_data, false, db.version()); - extract_joint_group(ag_file, db.dts, db.version(), art_group_data); + if (db.obj_files_by_name.count(dgo_name)) { + const auto& files = db.obj_files_by_dgo.at(dgo_name); + for (const auto& file : files) { + if (file.name.length() > 3 && !file.name.compare(file.name.length() - 3, 3, "-ag")) { + const auto& ag_file = db.lookup_record(file); + extract_merc(ag_file, tex_db, db.dts, tex_remap, level_data, false, db.version()); + extract_joint_group(ag_file, db.dts, db.version(), art_group_data); + } } } } @@ -281,6 +282,9 @@ void extract_common(const ObjectFileDB& db, add_all_textures_from_level(tfrag_level, dgo_name, tex_db); extract_art_groups_from_level(db, tex_db, {}, dgo_name, tfrag_level, art_group_data); + add_all_textures_from_level(tfrag_level, "ARTSPOOL", tex_db); + extract_art_groups_from_level(db, tex_db, {}, "ARTSPOOL", tfrag_level, art_group_data); + std::set textures_we_have; // put _all_ index textures in common. diff --git a/decompiler/main.cpp b/decompiler/main.cpp index ce1d87239b..f0e4d7bfcd 100644 --- a/decompiler/main.cpp +++ b/decompiler/main.cpp @@ -132,7 +132,7 @@ int main(int argc, char** argv) { mem_log("After init: {} MB\n", get_peak_rss() / (1024 * 1024)); - std::vector dgos, objs, strs, tex_strs; + std::vector dgos, objs, strs, tex_strs, art_strs; for (const auto& dgo_name : config.dgo_names) { dgos.push_back(in_folder / dgo_name); } @@ -149,11 +149,16 @@ int main(int argc, char** argv) { tex_strs.push_back(in_folder / str_name); } + for (const auto& str_name : config.str_art_file_names) { + art_strs.push_back(in_folder / str_name); + } + mem_log("After config read: {} MB", get_peak_rss() / (1024 * 1024)); // build file database lg::info("Setting up object file DB..."); - ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, config); + ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, strs, tex_strs, art_strs, + config); // Explicitly fail if a file in the 'allowed_objects' list wasn't found in the DB // as this is another silent error that can be confusing diff --git a/goal_src/jak3/engine/gfx/blit-displays.gc b/goal_src/jak3/engine/gfx/blit-displays.gc index 200536e4de..630bf633f9 100644 --- a/goal_src/jak3/engine/gfx/blit-displays.gc +++ b/goal_src/jak3/engine/gfx/blit-displays.gc @@ -83,5 +83,12 @@ ) ) +;; stub: + +(defmethod blit-displays-work-method-19 ((this blit-displays-work)) + (set! (-> this slow-time) (- 1.0 (-> *setting-control* user-current slow-time))) + (none) + ) + ;; DECOMP BEGINS diff --git a/goalc/build_level/jak1/build_level.cpp b/goalc/build_level/jak1/build_level.cpp index 9f3afb7ab7..15df0e3d70 100644 --- a/goalc/build_level/jak1/build_level.cpp +++ b/goalc/build_level/jak1/build_level.cpp @@ -145,7 +145,7 @@ bool run_build_level(const std::string& input_file, objs.push_back(iso_folder / obj_name); } - decompiler::ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, {}, + decompiler::ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, {}, {}, config); // need to process link data for tpages diff --git a/goalc/build_level/jak2/build_level.cpp b/goalc/build_level/jak2/build_level.cpp index 9b37329aee..97a9e4c691 100644 --- a/goalc/build_level/jak2/build_level.cpp +++ b/goalc/build_level/jak2/build_level.cpp @@ -132,7 +132,7 @@ bool run_build_level(const std::string& input_file, objs.push_back(iso_folder / obj_name); } - decompiler::ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, {}, + decompiler::ObjectFileDB db(dgos, fs::path(config.obj_file_name_map_file), objs, {}, {}, {}, config); // need to process link data for tpages diff --git a/test/offline/framework/orchestration.cpp b/test/offline/framework/orchestration.cpp index 15c167d8c9..c33b9af88c 100644 --- a/test/offline/framework/orchestration.cpp +++ b/test/offline/framework/orchestration.cpp @@ -50,7 +50,7 @@ OfflineTestDecompiler setup_decompiler(const OfflineTestWorkGroup& work, dc.db = std::make_unique( dgo_paths, dc.config->obj_file_name_map_file, std::vector{}, - std::vector{}, std::vector{}, *dc.config); + std::vector{}, std::vector{}, std::vector{}, *dc.config); dc.db->dts.art_group_info = dc.config->art_group_info_dump; dc.db->dts.jg_info = dc.config->jg_info_dump; dc.db->dts.textures = dc.config->texture_info_dump;