Compare commits
2 commits
2bc7751d3b
...
6e10d022e5
Author | SHA1 | Date | |
---|---|---|---|
6e10d022e5 | |||
3e9abd62c9 |
1 changed files with 44 additions and 79 deletions
123
oodle-cli.cpp
123
oodle-cli.cpp
|
@ -25,26 +25,24 @@ const char* LIB_FILE = "oo2core_8_win64.dll";
|
|||
typedef decltype(OodleLZ_Decompress)* decompress_func;
|
||||
typedef decltype(OodleCore_Plugins_SetPrintf)* setprintf_func;
|
||||
|
||||
#define OK 0
|
||||
#define GENERIC_ERROR -1
|
||||
#define DECOMPRESS_ERROR -2
|
||||
|
||||
void usage() {
|
||||
std::cerr <<
|
||||
"Usage: oodle-cli [OPTIONS] [--] <in_file> <out_file> <uncompressed_size>\n"
|
||||
"Decompress a <in_file> to <out_file> using the Oodle algorithm.\n"
|
||||
"The size of the uncompressed data must be known. If 0 is given, the tool will\n"
|
||||
"attempt to brute-force the correct number by incrementing from the compressed size.\n"
|
||||
"The size of the uncompressed data must be known.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -v Increase Oodle's verbosity. May be specified up to three times.\n"
|
||||
" -c Only check if the library can be found and used.\n"
|
||||
" --guess <number> When guessing the uncompressed size, a maximum number as multiple of the compressed size prevents an infinite loop. This changes the factor. Defaults to 10."
|
||||
" --fuzz-safe Use fuzz safe decompression.\n"
|
||||
" --check-crc Check CRC during decompression.\n"
|
||||
"\n"
|
||||
"The following environmental variables are recognized:\n"
|
||||
" DLL_SEARCH_PATH: A color (':') separated list of directories to search for the Oodle library. May be relative to the current working directory.\n";
|
||||
}
|
||||
|
||||
|
||||
void printf_callback(int verboseLevel, const char* file, int line, const char* fmt, ...) {
|
||||
std::cout << "[OODLE] ";
|
||||
|
||||
|
@ -66,51 +64,13 @@ void printf_callback(int verboseLevel, const char* file, int line, const char* f
|
|||
vfprintf(stdout, fmt, args);
|
||||
}
|
||||
|
||||
int do_decompress(decompress_func decompress, std::vector<char> compressed_buffer, std::string out_name, size_t raw_buffer_size, OodleLZ_Verbosity verbosity) {
|
||||
std::vector<char> raw_buffer(raw_buffer_size);
|
||||
|
||||
intptr_t res = decompress(
|
||||
compressed_buffer.data(),
|
||||
compressed_buffer.size(),
|
||||
raw_buffer.data(),
|
||||
raw_buffer_size,
|
||||
OodleLZ_FuzzSafe_Yes,
|
||||
OodleLZ_CheckCRC_No,
|
||||
verbosity,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
OodleLZ_Decode_Unthreaded
|
||||
);
|
||||
|
||||
if (res != raw_buffer_size) {
|
||||
return DECOMPRESS_ERROR;
|
||||
}
|
||||
|
||||
std::ofstream out_file(out_name, std::ios::binary);
|
||||
if (!out_file) {
|
||||
std::cerr << "ERROR: Failed to open output file!\n";
|
||||
return GENERIC_ERROR;
|
||||
}
|
||||
|
||||
out_file.write(raw_buffer.data(), res);
|
||||
|
||||
if (out_file.fail()) {
|
||||
std::cerr << "ERROR: Failed to write output file!\n";
|
||||
return GENERIC_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int verbosity = 0;
|
||||
bool check_lib = FALSE;
|
||||
int guess_factor = 10;
|
||||
OodleLZ_FuzzSafe fuzz_safe = OodleLZ_FuzzSafe_No;
|
||||
OodleLZ_CheckCRC check_crc = OodleLZ_CheckCRC_No;
|
||||
int i = 1;
|
||||
|
||||
for (; i < argc; i++) {
|
||||
|
@ -130,12 +90,16 @@ int main(int argc, char* argv[])
|
|||
else if (strcmp(arg, "-v") == 0) {
|
||||
verbosity++;
|
||||
}
|
||||
else if (strcmp(arg, "--guess") == 0) {
|
||||
i++;
|
||||
guess_factor = std::stoi(argv[i]);
|
||||
else if (strcmp(arg, "--fuzz-safe") == 0) {
|
||||
fuzz_safe = OodleLZ_FuzzSafe_Yes;
|
||||
}
|
||||
else if (strcmp(arg, "--check-crc") == 0) {
|
||||
check_crc = OodleLZ_CheckCRC_Yes;
|
||||
}
|
||||
else {
|
||||
std::cerr << "WARN: Unknown option '" << arg << "'!\n\n";
|
||||
std::cerr << "ERROR: Unknown option '" << arg << "'!\n\n";
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,40 +189,41 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (raw_buffer_size > 0) {
|
||||
int res = do_decompress(decompress, compressed_buffer, out_name, raw_buffer_size, (OodleLZ_Verbosity)verbosity);
|
||||
std::vector<char> raw_buffer(raw_buffer_size);
|
||||
|
||||
if (res == DECOMPRESS_ERROR) {
|
||||
std::cerr << "ERROR: Failed to decompress!\n";
|
||||
return 1;
|
||||
}
|
||||
else if (res == GENERIC_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
intptr_t res = decompress(
|
||||
compressed_buffer.data(),
|
||||
compressed_buffer.size(),
|
||||
raw_buffer.data(),
|
||||
raw_buffer_size,
|
||||
fuzz_safe,
|
||||
check_crc,
|
||||
(OodleLZ_Verbosity)verbosity,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
OodleLZ_Decode_Unthreaded
|
||||
);
|
||||
|
||||
if (res != raw_buffer_size) {
|
||||
std::cerr << "ERROR: Failed to decompress!\n";
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
size_t guessed_size = compressed_buffer.size();
|
||||
// I need some maximum value to avoid infinite loops. The factor is configurable.
|
||||
size_t max = guessed_size * guess_factor;
|
||||
|
||||
while (true) {
|
||||
int res = do_decompress(decompress, compressed_buffer, out_name, guessed_size, (OodleLZ_Verbosity)verbosity);
|
||||
|
||||
if (res == GENERIC_ERROR) {
|
||||
return 1;
|
||||
}
|
||||
else if (res == OK) {
|
||||
std::cout << "INFO: Found decompressed size as " << guessed_size << "\n";
|
||||
break;
|
||||
}
|
||||
std::ofstream out_file(out_name, std::ios::binary);
|
||||
if (!out_file) {
|
||||
std::cerr << "ERROR: Failed to open output file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
guessed_size++;
|
||||
out_file.write(raw_buffer.data(), res);
|
||||
|
||||
if (guessed_size > max) {
|
||||
std::cerr << "ERROR: Exceeded maximum value for guessing uncompressed size!\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (out_file.fail()) {
|
||||
std::cerr << "ERROR: Failed to write output file!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "INFO: Done!\n";
|
||||
|
|
Reference in a new issue