mirror of
https://github.com/open-goal/jak-project
synced 2026-08-22 07:04:29 -04:00
full ntsc-j mode + greatest hits support (#1525)
* remove str files from inputs * removed unused verbose flag * allow some kind of conditional game building for JP extras * make `PrintBankInfo` do nothing * clang * Update gltf_mesh_extract.cpp * fix `*jak1-full-game*` in extractor * use json library to build json file * screw it red label support as well
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
#include <map>
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/log/log.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "common/util/json_util.h"
|
||||
#include "common/util/read_iso_file.h"
|
||||
|
||||
#include "decompiler/Disasm/OpcodeInfo.h"
|
||||
@@ -23,12 +26,18 @@ enum class ExtractorErrorCode {
|
||||
DECOMPILATION_GENERIC_ERROR = 4030
|
||||
};
|
||||
|
||||
enum GameIsoFlags { FLAG_JAK1_BLACK_LABEL = (1 << 0) };
|
||||
|
||||
static const std::unordered_map<std::string, GameIsoFlags> sGameIsoFlagNames = {
|
||||
{"jak1-black-label", FLAG_JAK1_BLACK_LABEL}};
|
||||
|
||||
struct ISOMetadata {
|
||||
std::string canonical_name;
|
||||
std::string region;
|
||||
int num_files;
|
||||
xxh::hash64_t contents_hash;
|
||||
std::string decomp_config;
|
||||
GameIsoFlags flags = (GameIsoFlags)0;
|
||||
};
|
||||
|
||||
// TODO - when we support jak2 and beyond, add which game it's for as well
|
||||
@@ -39,11 +48,12 @@ static const std::map<std::string, std::map<xxh::hash64_t, ISOMetadata>> isoData
|
||||
{"SCUS-97124",
|
||||
{{7280758013604870207U,
|
||||
{"Jak & Daxter™: The Precursor Legacy (Black Label)", "NTSC-U", 337, 11363853835861842434U,
|
||||
"jak1_ntsc_black_label"}}}},
|
||||
"jak1_ntsc_black_label", FLAG_JAK1_BLACK_LABEL}},
|
||||
{744661860962747854,
|
||||
{"Jak & Daxter™: The Precursor Legacy", "NTSC-U", 338, 8538304367812415885U, "jak1_jp"}}}},
|
||||
{"SCES-50361",
|
||||
{{12150718117852276522U,
|
||||
{"Jak & Daxter™: The Precursor Legacy (PAL)", "PAL", 338, 16850370297611763875U,
|
||||
"jak1_pal"}}}},
|
||||
{"Jak & Daxter™: The Precursor Legacy", "PAL", 338, 16850370297611763875U, "jak1_pal"}}}},
|
||||
{"SCPS-15021",
|
||||
{{16909372048085114219U,
|
||||
{"ジャックXダクスター ~ 旧世界の遺産", "NTSC-J", 338, 1262350561338887717,
|
||||
@@ -90,11 +100,12 @@ std::pair<std::optional<std::string>, std::optional<xxh::hash64_t>> findElfFile(
|
||||
return {serial, elf_hash};
|
||||
}
|
||||
|
||||
ExtractorErrorCode validate(const IsoFile& iso_file,
|
||||
const std::filesystem::path& extracted_iso_path) {
|
||||
std::pair<ExtractorErrorCode, std::optional<ISOMetadata>> validate(
|
||||
const IsoFile& iso_file,
|
||||
const std::filesystem::path& extracted_iso_path) {
|
||||
if (!std::filesystem::exists(extracted_iso_path / "DGO")) {
|
||||
fmt::print(stderr, "ERROR: input folder doesn't have a DGO folder. Is this the right input?\n");
|
||||
return ExtractorErrorCode::VALIDATION_BAD_EXTRACTION;
|
||||
return {ExtractorErrorCode::VALIDATION_BAD_EXTRACTION, std::nullopt};
|
||||
}
|
||||
|
||||
std::optional<ExtractorErrorCode> error_code;
|
||||
@@ -116,10 +127,11 @@ ExtractorErrorCode validate(const IsoFile& iso_file,
|
||||
error_code = std::make_optional(ExtractorErrorCode::VALIDATION_CANT_LOCATE_ELF);
|
||||
}
|
||||
// No point in continuing here
|
||||
return error_code.value();
|
||||
return {*error_code, std::nullopt};
|
||||
}
|
||||
|
||||
// Find the game in our tracking database
|
||||
std::optional<ISOMetadata> meta_res = std::nullopt;
|
||||
if (auto dbEntry = isoDatabase.find(serial.value()); dbEntry == isoDatabase.end()) {
|
||||
fmt::print(stderr, "ERROR: Serial '{}' not found in the validation database\n", serial.value());
|
||||
if (!error_code.has_value()) {
|
||||
@@ -137,7 +149,8 @@ ExtractorErrorCode validate(const IsoFile& iso_file,
|
||||
error_code = std::make_optional(ExtractorErrorCode::VALIDATION_ELF_MISSING_FROM_DB);
|
||||
}
|
||||
} else {
|
||||
auto meta = meta_entry->second;
|
||||
meta_res = std::make_optional<ISOMetadata>(meta_entry->second);
|
||||
const auto& meta = *meta_res;
|
||||
// Print out some information
|
||||
fmt::print("Detected Game Metadata:\n");
|
||||
fmt::print("\tDetected - {}\n", meta.canonical_name);
|
||||
@@ -189,10 +202,10 @@ ExtractorErrorCode validate(const IsoFile& iso_file,
|
||||
"Validation has failed to match with expected values, see the above errors for "
|
||||
"specifics. This may be an error in the validation database!\n");
|
||||
}
|
||||
return error_code.value();
|
||||
return {*error_code, std::nullopt};
|
||||
}
|
||||
|
||||
return ExtractorErrorCode::SUCCESS;
|
||||
return {ExtractorErrorCode::SUCCESS, meta_res};
|
||||
}
|
||||
|
||||
std::optional<ISOMetadata> determineRelease(const std::filesystem::path& jak1_input_files) {
|
||||
@@ -313,6 +326,17 @@ void compile(std::filesystem::path extracted_iso_path) {
|
||||
compiler.make_system().set_constant("*iso-data*", absolute(extracted_iso_path).string());
|
||||
compiler.make_system().set_constant("*use-iso-data-path*", true);
|
||||
|
||||
auto buildinfo_path = (extracted_iso_path / "buildinfo.json").string();
|
||||
auto bi = parse_commented_json(file_util::read_text_file(buildinfo_path), buildinfo_path);
|
||||
auto all_flags = bi.at("flags").get<std::vector<std::string>>();
|
||||
int flags = 0;
|
||||
for (const auto& n : all_flags) {
|
||||
if (auto it = sGameIsoFlagNames.find(n); it != sGameIsoFlagNames.end()) {
|
||||
flags |= it->second;
|
||||
}
|
||||
}
|
||||
compiler.make_system().set_constant("*jak1-full-game*", !(flags & FLAG_JAK1_BLACK_LABEL));
|
||||
|
||||
compiler.make_system().load_project_file(
|
||||
(file_util::get_jak_project_dir() / "goal_src" / "game.gp").string());
|
||||
compiler.run_front_end_on_string("(mi)");
|
||||
@@ -389,15 +413,17 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
std::filesystem::create_directories(path_to_iso_files);
|
||||
|
||||
int flags = 0;
|
||||
if (std::filesystem::is_regular_file(data_dir_path)) {
|
||||
// it's a file, treat it as an ISO
|
||||
auto iso_file = extract_files(data_dir_path, path_to_iso_files);
|
||||
auto validation_res = validate(iso_file, path_to_iso_files);
|
||||
if (validation_res == ExtractorErrorCode::VALIDATION_BAD_EXTRACTION) {
|
||||
flags = validation_res.second->flags;
|
||||
if (validation_res.first == ExtractorErrorCode::VALIDATION_BAD_EXTRACTION) {
|
||||
// We fail here regardless of the flag
|
||||
return static_cast<int>(validation_res);
|
||||
} else if (flag_fail_on_validation && validation_res != ExtractorErrorCode::SUCCESS) {
|
||||
return static_cast<int>(validation_res);
|
||||
return static_cast<int>(validation_res.first);
|
||||
} else if (flag_fail_on_validation && validation_res.first != ExtractorErrorCode::SUCCESS) {
|
||||
return static_cast<int>(validation_res.first);
|
||||
}
|
||||
} else if (std::filesystem::is_directory(data_dir_path)) {
|
||||
if (!flag_folder) {
|
||||
@@ -407,6 +433,19 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
path_to_iso_files = data_dir_path;
|
||||
}
|
||||
|
||||
// write out a json file with some metadata for the game
|
||||
nlohmann::json buildinfo_json;
|
||||
auto flags_json = nlohmann::json::array();
|
||||
for (const auto& [n, f] : sGameIsoFlagNames) {
|
||||
if (flags & f) {
|
||||
flags_json.push_back(n);
|
||||
}
|
||||
}
|
||||
buildinfo_json["flags"] = flags_json;
|
||||
// something tells me a ps2 game is unlikely to have a json file in root
|
||||
file_util::write_text_file((path_to_iso_files / "buildinfo.json").string(),
|
||||
buildinfo_json.dump(2));
|
||||
}
|
||||
|
||||
if (flag_decompile) {
|
||||
|
||||
Reference in New Issue
Block a user