mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 15:02:01 -04:00
[decompiler] jak 2 cutscene file support (#2390)
fixes #2332 also fills out the japanese character set
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "decompiler/data/StrFileReader.h"
|
||||
#include "decompiler/data/dir_tpages.h"
|
||||
#include "decompiler/data/game_count.h"
|
||||
#include "decompiler/data/game_subs.h"
|
||||
#include "decompiler/data/game_text.h"
|
||||
#include "decompiler/data/tpage.h"
|
||||
|
||||
@@ -204,18 +205,20 @@ ObjectFileDB::ObjectFileDB(const std::vector<fs::path>& _dgos,
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
|
||||
}
|
||||
|
||||
lg::info("-Loading {} streaming object files...", str_files.size());
|
||||
for (auto& obj : str_files) {
|
||||
StrFileReader reader(obj);
|
||||
// name from the file name
|
||||
std::string base_name = obj_filename_to_name(obj.string());
|
||||
// name from inside the file (this does a lot of sanity checking)
|
||||
auto obj_name = reader.get_full_name(base_name + ".STR");
|
||||
for (int i = 0; i < reader.chunk_count(); i++) {
|
||||
// append the chunk ID to the full name
|
||||
std::string name = obj_name + fmt::format("+{}", i);
|
||||
auto& data = reader.get_chunk(i);
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
|
||||
if (config.read_spools) {
|
||||
lg::info("-Loading {} streaming object files...", str_files.size());
|
||||
for (auto& obj : str_files) {
|
||||
StrFileReader reader(obj, version());
|
||||
// name from the file name
|
||||
std::string base_name = obj_filename_to_name(obj.string());
|
||||
// name from inside the file (this does a lot of sanity checking)
|
||||
auto obj_name = reader.get_full_name(base_name + ".STR");
|
||||
for (int i = 0; i < reader.chunk_count(); i++) {
|
||||
// append the chunk ID to the full name
|
||||
std::string name = obj_name + fmt::format("+{}", i);
|
||||
auto& data = reader.get_chunk(i);
|
||||
add_obj_from_dgo(name, name, data.data(), data.size(), "ALLSPOOL", config, obj_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +372,8 @@ void ObjectFileDB::add_obj_from_dgo(const std::string& obj_name,
|
||||
const uint8_t* obj_data,
|
||||
uint32_t obj_size,
|
||||
const std::string& dgo_name,
|
||||
const Config& config) {
|
||||
const Config& config,
|
||||
const std::string& cut_name) {
|
||||
if (config.banned_objects.find(obj_name) != config.banned_objects.end()) {
|
||||
return;
|
||||
}
|
||||
@@ -415,6 +419,7 @@ void ObjectFileDB::add_obj_from_dgo(const std::string& obj_name,
|
||||
// if this is the first time we've seen this object file name, add it in the order.
|
||||
obj_file_order.push_back(obj_name);
|
||||
}
|
||||
data.base_name_from_chunk = cut_name;
|
||||
data.record.version = obj_files_by_name[obj_name].size();
|
||||
data.name_in_dgo = name_in_dgo;
|
||||
data.obj_version = version;
|
||||
@@ -489,9 +494,10 @@ std::string ObjectFileDB::generate_obj_listing(const std::unordered_set<std::str
|
||||
for (auto& obj_file : obj_file_order) {
|
||||
for (auto& x : obj_files_by_name.at(obj_file)) {
|
||||
std::string dgos = "[";
|
||||
for (auto& y : x.dgo_names) {
|
||||
ASSERT(y.length() >= 5);
|
||||
std::string new_str = y == "NO-XGO" ? y : y.substr(0, y.length() - 4);
|
||||
for (auto& name : x.dgo_names) {
|
||||
ASSERT(name.length() >= 5);
|
||||
std::string new_str =
|
||||
(name == "NO-XGO" || name == "ALLSPOOL") ? name : name.substr(0, name.length() - 4);
|
||||
dgos += "\"" + new_str + "\", ";
|
||||
}
|
||||
dgos.pop_back();
|
||||
@@ -725,6 +731,58 @@ std::string ObjectFileDB::process_tpages(TextureDB& tex_db, const fs::path& outp
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string ObjectFileDB::process_all_spool_subtitles(const Config& cfg,
|
||||
const fs::path& image_out) {
|
||||
try {
|
||||
lg::info("- Finding spool subtitles...");
|
||||
Timer timer;
|
||||
int obj_count = 0;
|
||||
int string_count = 0;
|
||||
int image_count = 0;
|
||||
int subs_count = 0;
|
||||
std::unordered_map<std::string, std::vector<SpoolSubtitleRange>> all_subs;
|
||||
|
||||
for_each_obj_in_dgo("ALLSPOOL", [&](ObjectFileData& data) {
|
||||
int this_string_count = 0;
|
||||
int this_image_count = 0;
|
||||
obj_count++;
|
||||
auto this_spool_subs = process_spool_subtitles(data, cfg.text_version);
|
||||
if (!this_spool_subs.empty()) {
|
||||
for (auto& s : this_spool_subs) {
|
||||
subs_count++;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (s.message[i].kind == SpoolSubtitleMessage::Kind::IMAGE) {
|
||||
this_image_count++;
|
||||
} else if (s.message[i].kind == SpoolSubtitleMessage::Kind::STRING) {
|
||||
this_string_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto& spool_subs = all_subs[data.base_name_from_chunk];
|
||||
for (auto& x : this_spool_subs) {
|
||||
bool skip = false;
|
||||
for (auto& other : spool_subs) {
|
||||
skip |= other == x;
|
||||
}
|
||||
if (!skip) {
|
||||
all_subs[data.base_name_from_chunk].push_back(x);
|
||||
image_count += this_image_count;
|
||||
string_count += this_string_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
lg::info("Processed {} subtitles in {} spool objects ({} strings, {} images) in {:.2f} ms",
|
||||
subs_count, obj_count, string_count, image_count, timer.getMs());
|
||||
|
||||
return write_spool_subtitles(cfg.text_version, image_out, all_subs);
|
||||
} catch (std::runtime_error& e) {
|
||||
lg::warn("Error when extracting spool subtitles: {}", e.what());
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::string ObjectFileDB::process_game_text_files(const Config& cfg) {
|
||||
try {
|
||||
lg::info("- Finding game text...");
|
||||
|
||||
Reference in New Issue
Block a user