make it obvious how to compress/decompress prc files

This commit is contained in:
Martin Michelsen
2023-12-28 09:14:00 -08:00
parent c1122e1f90
commit 5307051e04
2 changed files with 24 additions and 15 deletions
+1 -1
View File
@@ -431,7 +431,7 @@ For GC clients, you'll have to use newserv's built-in DNS server or set up your
newserv has many CLI options, which can be used to access functionality other than the game and proxy server. Run `newserv help` to see these options and how to use them. The non-server things newserv can do are: newserv has many CLI options, which can be used to access functionality other than the game and proxy server. Run `newserv help` to see these options and how to use them. The non-server things newserv can do are:
* Compress or decompress data in PRS, PR2, or BC0 format (`compress-prs`, `compress-pr2`, `compress-bc0`, `decompress-prs`, `decompress-pr2`, `decompress-bc0`) * Compress or decompress data in PRS, PR2/PRC, or BC0 format (`compress-prs`, `compress-pr2`, `compress-bc0`, `decompress-prs`, `decompress-pr2`, `decompress-bc0`)
* Compute the decompressed size of compressed PRS data without decompressing it (`prs-size`) * Compute the decompressed size of compressed PRS data without decompressing it (`prs-size`)
* Encrypt or decrypt data using any PSO version's network encryption scheme (`encrypt-data`, `decrypt-data`) * Encrypt or decrypt data using any PSO version's network encryption scheme (`encrypt-data`, `decrypt-data`)
* Encrypt or decrypt data using Episode 3's trivial scheme (`encrypt-trivial-data`, `decrypt-trivial-data`) * Encrypt or decrypt data using Episode 3's trivial scheme (`encrypt-trivial-data`, `decrypt-trivial-data`)
+18 -9
View File
@@ -221,6 +221,7 @@ static void a_compress_decompress_fn(Arguments& args) {
bool is_prs = ends_with(action, "-prs"); bool is_prs = ends_with(action, "-prs");
bool is_bc0 = ends_with(action, "-bc0"); bool is_bc0 = ends_with(action, "-bc0");
bool is_pr2 = ends_with(action, "-pr2"); bool is_pr2 = ends_with(action, "-pr2");
bool is_prc = ends_with(action, "-prc");
bool is_decompress = starts_with(action, "decompress-"); bool is_decompress = starts_with(action, "decompress-");
bool is_big_endian = args.get<bool>("big-endian"); bool is_big_endian = args.get<bool>("big-endian");
bool is_optimal = args.get<bool>("optimal"); bool is_optimal = args.get<bool>("optimal");
@@ -231,7 +232,7 @@ static void a_compress_decompress_fn(Arguments& args) {
string data = read_input_data(args); string data = read_input_data(args);
size_t pr2_expected_size = 0; size_t pr2_expected_size = 0;
if (is_decompress && is_pr2) { if (is_decompress && (is_pr2 || is_prc)) {
auto decrypted = is_big_endian ? decrypt_pr2_data<true>(data) : decrypt_pr2_data<false>(data); auto decrypted = is_big_endian ? decrypt_pr2_data<true>(data) : decrypt_pr2_data<false>(data);
pr2_expected_size = decrypted.decompressed_size; pr2_expected_size = decrypted.decompressed_size;
data = std::move(decrypted.compressed_data); data = std::move(decrypted.compressed_data);
@@ -253,13 +254,13 @@ static void a_compress_decompress_fn(Arguments& args) {
}; };
uint64_t start = now(); uint64_t start = now();
if (!is_decompress && (is_prs || is_pr2)) { if (!is_decompress && (is_prs || is_pr2 || is_prc)) {
if (is_optimal) { if (is_optimal) {
data = prs_compress_optimal(data.data(), data.size(), optimal_progress_fn); data = prs_compress_optimal(data.data(), data.size(), optimal_progress_fn);
} else { } else {
data = prs_compress(data, compression_level, progress_fn); data = prs_compress(data, compression_level, progress_fn);
} }
} else if (is_decompress && (is_prs || is_pr2)) { } else if (is_decompress && (is_prs || is_pr2 || is_prc)) {
data = prs_decompress(data, bytes, (bytes != 0)); data = prs_decompress(data, bytes, (bytes != 0));
} else if (!is_decompress && is_bc0) { } else if (!is_decompress && is_bc0) {
if (is_optimal) { if (is_optimal) {
@@ -283,14 +284,16 @@ static void a_compress_decompress_fn(Arguments& args) {
log_info("%zu (0x%zX) bytes input => %zu (0x%zX) bytes output (%g%%) in %s (%s / sec)", log_info("%zu (0x%zX) bytes input => %zu (0x%zX) bytes output (%g%%) in %s (%s / sec)",
input_bytes, input_bytes, data.size(), data.size(), size_ratio, time_str.c_str(), bytes_per_sec_str.c_str()); input_bytes, input_bytes, data.size(), data.size(), size_ratio, time_str.c_str(), bytes_per_sec_str.c_str());
if (is_decompress && is_pr2 && (data.size() != pr2_expected_size)) { if (is_pr2 || is_prc) {
if (is_decompress && (data.size() != pr2_expected_size)) {
log_warning("Result data size (%zu bytes) does not match expected size from PR2 header (%zu bytes)", data.size(), pr2_expected_size); log_warning("Result data size (%zu bytes) does not match expected size from PR2 header (%zu bytes)", data.size(), pr2_expected_size);
} else if (!is_decompress && is_pr2) { } else if (!is_decompress) {
uint32_t pr2_seed = seed.empty() ? random_object<uint32_t>() : stoul(seed, nullptr, 16); uint32_t pr2_seed = seed.empty() ? random_object<uint32_t>() : stoul(seed, nullptr, 16);
data = is_big_endian data = is_big_endian
? encrypt_pr2_data<true>(data, input_bytes, pr2_seed) ? encrypt_pr2_data<true>(data, input_bytes, pr2_seed)
: encrypt_pr2_data<false>(data, input_bytes, pr2_seed); : encrypt_pr2_data<false>(data, input_bytes, pr2_seed);
} }
}
const char* extension; const char* extension;
if (is_decompress) { if (is_decompress) {
@@ -299,6 +302,8 @@ static void a_compress_decompress_fn(Arguments& args) {
extension = "prs"; extension = "prs";
} else if (is_bc0) { } else if (is_bc0) {
extension = "bc0"; extension = "bc0";
} else if (is_prc) {
extension = "prc";
} else if (is_pr2) { } else if (is_pr2) {
extension = "pr2"; extension = "pr2";
} else { } else {
@@ -309,11 +314,13 @@ static void a_compress_decompress_fn(Arguments& args) {
Action a_compress_prs("compress-prs", nullptr, a_compress_decompress_fn); Action a_compress_prs("compress-prs", nullptr, a_compress_decompress_fn);
Action a_compress_bc0("compress-bc0", nullptr, a_compress_decompress_fn); Action a_compress_bc0("compress-bc0", nullptr, a_compress_decompress_fn);
Action a_compress_pr2("compress-pr2", "\ Action a_compress_pr2("compress-pr2", nullptr, a_compress_decompress_fn);
Action a_compress_prc("compress-prc", "\
compress-prs [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ compress-prs [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
compress-pr2 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ compress-pr2 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
compress-prc [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
compress-bc0 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ compress-bc0 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Compress data using the PRS, PR2, or BC0 algorithms. By default, the\n\ Compress data using the PRS, PR2, PRC, or BC0 algorithms. By default, the\n\
heuristic-based compressor is used, which gives a good balance between\n\ heuristic-based compressor is used, which gives a good balance between\n\
memory usage, CPU usage, and output size. For PRS and PR2, this compressor\n\ memory usage, CPU usage, and output size. For PRS and PR2, this compressor\n\
can be tuned with the --compression-level=N option, which specifies how\n\ can be tuned with the --compression-level=N option, which specifies how\n\
@@ -328,11 +335,13 @@ Action a_compress_pr2("compress-pr2", "\
a_compress_decompress_fn); a_compress_decompress_fn);
Action a_decompress_prs("decompress-prs", nullptr, a_compress_decompress_fn); Action a_decompress_prs("decompress-prs", nullptr, a_compress_decompress_fn);
Action a_decompress_bc0("decompress-bc0", nullptr, a_compress_decompress_fn); Action a_decompress_bc0("decompress-bc0", nullptr, a_compress_decompress_fn);
Action a_decompress_pr2("decompress-pr2", "\ Action a_decompress_pr2("decompress-pr2", nullptr, a_compress_decompress_fn);
Action a_decompress_prc("decompress-prc", "\
decompress-prs [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ decompress-prs [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
decompress-pr2 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ decompress-pr2 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
decompress-prc [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
decompress-bc0 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\ decompress-bc0 [INPUT-FILENAME [OUTPUT-FILENAME]]\n\
Decompress data compressed using the PRS, PR2, or BC0 algorithms.\n", Decompress data compressed using the PRS, PR2, PRC, or BC0 algorithms.\n",
a_compress_decompress_fn); a_compress_decompress_fn);
Action a_prs_size( Action a_prs_size(