mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-04-10 19:31:31 -06:00
implement basic cli compress/decompress feature
This commit is contained in:
parent
e351fa56ce
commit
d5cf5f45c3
@ -336,6 +336,46 @@ GMainWindow::GMainWindow(Core::System& system_)
|
||||
game_path = args[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compress files in place
|
||||
if (args[i] == QStringLiteral("--compress") || args[i] == QStringLiteral("-c")) {
|
||||
if (i >= args.size() - 1 || args[i + 1].startsWith(QChar::fromLatin1('-'))) {
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
for (; i < args.size(); i++){
|
||||
QFileInfo currPath(args[i]);
|
||||
if (currPath.isFile()){
|
||||
compress_paths.append(args[i]);
|
||||
} else {
|
||||
QTextStream(stderr) << "Error: " << args[i] << " is not a file!\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
GMainWindow::OnCompressFileCLI();
|
||||
compression_future.waitForFinished();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Decompress files in place
|
||||
if (args[i] == QStringLiteral("--decompress") || args[i] == QStringLiteral("-x")) {
|
||||
if (i >= args.size() - 1 || args[i + 1].startsWith(QChar::fromLatin1('-'))) {
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
for (; i < args.size(); i++){
|
||||
QFileInfo currPath(args[i]);
|
||||
if (currPath.isFile()){
|
||||
decompress_paths.append(args[i]);
|
||||
} else {
|
||||
QTextStream(stderr) << "Error: " << args[i] << " is not a file!\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
GMainWindow::OnDecompressFileCLI();
|
||||
compression_future.waitForFinished();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __unix__
|
||||
@ -3281,6 +3321,72 @@ void GMainWindow::OnCompressFile() {
|
||||
});
|
||||
}
|
||||
|
||||
void GMainWindow::OnCompressFileCLI() {
|
||||
// NOTE: Encrypted files SHOULD NEVER be compressed, otherwise the resulting
|
||||
// compressed file will have very poor compression ratios, due to the high
|
||||
// entropy caused by encryption. This may cause confusion to the user as they
|
||||
// will see the files do not compress well and blame the emulator.
|
||||
//
|
||||
// This is enforced using the loaders as they already return an error on encryption.
|
||||
|
||||
QString out_path;
|
||||
QStringList filepaths = compress_paths;
|
||||
if (compress_paths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool single_file = filepaths.size() == 1;
|
||||
|
||||
// Set the output directory based on the starting file
|
||||
QFileInfo startFileInfo(filepaths[0]);
|
||||
out_path = startFileInfo.absolutePath();
|
||||
if (out_path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
compression_future = QtConcurrent::run([&, filepaths, out_path] {
|
||||
bool single_file = filepaths.size() == 1;
|
||||
QString out_filepath;
|
||||
bool total_success = true;
|
||||
|
||||
for (const QString& filepath : filepaths) {
|
||||
QFileInfo filepathInfo(filepath);
|
||||
QTextStream(stdout) << "Compressing " << filepathInfo.fileName() << "\n";
|
||||
std::string in_path = filepath.toStdString();
|
||||
|
||||
// Identify file type
|
||||
auto compress_info = GetCompressFileInfo(filepath.toStdString(), true);
|
||||
if (!compress_info.has_value()) {
|
||||
total_success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo fileinfo(filepath);
|
||||
out_filepath = out_path + QStringLiteral(DIR_SEP) + fileinfo.completeBaseName() +
|
||||
QStringLiteral(".") +
|
||||
QString::fromStdString(
|
||||
compress_info.value().first.recommended_compressed_extension);
|
||||
|
||||
std::string out_path = out_filepath.toStdString();
|
||||
emit UpdateProgress(0, 0);
|
||||
const auto progress = [&](std::size_t written, std::size_t total) {
|
||||
emit UpdateProgress(written, total);
|
||||
};
|
||||
bool success = FileUtil::CompressZ3DSFile(in_path, out_path,
|
||||
compress_info.value().first.underlying_magic,
|
||||
compress_info.value().second, progress,
|
||||
compress_info.value().first.default_metadata);
|
||||
if (!success) {
|
||||
total_success = false;
|
||||
FileUtil::Delete(out_path);
|
||||
}
|
||||
}
|
||||
emit CompressFinished(true, total_success);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GMainWindow::OnDecompressFile() {
|
||||
|
||||
QStringList filepaths = QFileDialog::getOpenFileNames(
|
||||
@ -3374,6 +3480,58 @@ void GMainWindow::OnDecompressFile() {
|
||||
});
|
||||
}
|
||||
|
||||
void GMainWindow::OnDecompressFileCLI() {
|
||||
QStringList filepaths = decompress_paths;
|
||||
QString out_path;
|
||||
|
||||
if (filepaths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool single_file = filepaths.size() == 1;
|
||||
QFileInfo startFileInfo(filepaths[0]);
|
||||
out_path = startFileInfo.absolutePath();
|
||||
|
||||
compression_future = QtConcurrent::run([&, filepaths, out_path] {
|
||||
bool single_file = filepaths.size() == 1;
|
||||
QString out_filepath;
|
||||
bool total_success = true;
|
||||
|
||||
for (const QString& filepath : filepaths) {
|
||||
QFileInfo filepathInfo(filepath);
|
||||
QTextStream(stdout) << "Decompressing " << filepathInfo.fileName() << "\n";
|
||||
std::string in_path = filepath.toStdString();
|
||||
|
||||
// Identify file type
|
||||
auto compress_info = GetCompressFileInfo(filepath.toStdString(), false);
|
||||
if (!compress_info.has_value()) {
|
||||
total_success = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
QFileInfo fileinfo(filepath);
|
||||
|
||||
out_filepath = out_path + QStringLiteral(DIR_SEP) + fileinfo.completeBaseName() +
|
||||
QStringLiteral(".") +
|
||||
QString::fromStdString(
|
||||
compress_info.value().first.recommended_uncompressed_extension);
|
||||
std::string out_path = out_filepath.toStdString();
|
||||
emit UpdateProgress(0, 0);
|
||||
const auto progress = [&](std::size_t written, std::size_t total) {
|
||||
emit UpdateProgress(written, total);
|
||||
};
|
||||
|
||||
// TODO(PabloMK7): What should we do with the metadata?
|
||||
bool success = FileUtil::DeCompressZ3DSFile(in_path, out_path, progress);
|
||||
if (!success) {
|
||||
total_success = false;
|
||||
FileUtil::Delete(out_path);
|
||||
}
|
||||
}
|
||||
emit CompressFinished(false, total_success);
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void GMainWindow::OnOpenFFmpeg() {
|
||||
auto filename =
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <qfuture.h>
|
||||
#ifdef __unix__
|
||||
#include <QDBusObjectPath>
|
||||
#endif
|
||||
@ -290,7 +291,9 @@ private slots:
|
||||
void OnCaptureScreenshot();
|
||||
void OnDumpVideo();
|
||||
void OnCompressFile();
|
||||
void OnCompressFileCLI();
|
||||
void OnDecompressFile();
|
||||
void OnDecompressFileCLI();
|
||||
#ifdef _WIN32
|
||||
void OnOpenFFmpeg();
|
||||
#endif
|
||||
@ -397,6 +400,12 @@ private:
|
||||
// Video dumping
|
||||
bool video_dumping_on_start = false;
|
||||
QString video_dumping_path;
|
||||
|
||||
// Compress/Decompress Paths and Future
|
||||
QStringList compress_paths;
|
||||
QStringList decompress_paths;
|
||||
QFuture<void> compression_future;
|
||||
|
||||
// Whether game shutdown is delayed due to video dumping
|
||||
bool game_shutdown_delayed = false;
|
||||
// Whether game was paused due to stopping video dumping
|
||||
@ -404,7 +413,6 @@ private:
|
||||
|
||||
QString gl_renderer;
|
||||
std::vector<QString> physical_devices;
|
||||
|
||||
// Debugger panes
|
||||
ProfilerWidget* profilerWidget;
|
||||
#if MICROPROFILE_ENABLED
|
||||
|
||||
Loading…
Reference in New Issue
Block a user