mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Add really simple 7z extraction, using the 7z VFS
This commit is contained in:
@@ -36,6 +36,8 @@ static bool IsLocalAbsolutePath(std::string_view path) {
|
||||
return isUnixLocal || isWindowsLocal || isContentURI;
|
||||
}
|
||||
|
||||
// This allows empty prefixes for multiple systems, which effectively becomes a union mount.
|
||||
// Which is useful for PPSSPP's asset files, but not much else. We should use prefixes for everything.
|
||||
template<class RetType, class Func>
|
||||
inline RetType RouteVFSOperation(const std::vector<VFSEntry> &entries, std::string_view filename, Func func) {
|
||||
const int fn_len = (int)filename.length();
|
||||
|
||||
@@ -59,6 +59,8 @@ void OnScreenDisplay::Show(OSDType type, std::string_view text, std::string_view
|
||||
return;
|
||||
}
|
||||
|
||||
INFO_LOG(Log::UI, "OSD: %.*s (%.*s)", STR_VIEW(text), STR_VIEW(text2));
|
||||
|
||||
// Automatic duration based on type.
|
||||
if (duration_s <= 0.0f) {
|
||||
switch (type) {
|
||||
|
||||
@@ -451,7 +451,26 @@ static bool ZipExtractFileToMemory(struct zip *z, int fileIndex, std::string *da
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Make this generic and handle all the things.
|
||||
// For now, it'll just handle unpacking ISOs.
|
||||
bool DetectArchiveContents(VFSInterface *vfs, ZipFileInfo *info) {
|
||||
info->archiveType = ArchiveType::SevenZ;
|
||||
info->contents = ZipFileContents::UNKNOWN;
|
||||
std::vector<File::FileInfo> listing;
|
||||
vfs->GetFileListing("", &listing, nullptr);
|
||||
for (auto &file : listing) {
|
||||
std::string ext = file.fullName.GetFileExtension(); // always lowercase
|
||||
if (ext == ".iso" || ext == ".cso") {
|
||||
info->contents = ZipFileContents::ISO_FILE;
|
||||
info->isoFilename = file.fullName.ToString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DetectZipFileContents(zip_t *z, ZipFileInfo *info) {
|
||||
info->archiveType = ArchiveType::ZIP;
|
||||
int numFiles = zip_get_num_files(z);
|
||||
if (numFiles < 0) {
|
||||
// Broken zip archive?
|
||||
|
||||
+8
-1
@@ -162,6 +162,10 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorStrin
|
||||
|
||||
bool UmdReplace(const Path &filepath, FileLoader **fileLoader, std::string &error);
|
||||
|
||||
enum class ArchiveType {
|
||||
ZIP,
|
||||
SevenZ,
|
||||
};
|
||||
|
||||
enum class ZipFileContents {
|
||||
NOT_A_ZIP_FILE = 0,
|
||||
@@ -176,7 +180,9 @@ enum class ZipFileContents {
|
||||
PRX_PLUGIN,
|
||||
};
|
||||
|
||||
// TODO: Rename to ArchiveContentsInfo or something.
|
||||
struct ZipFileInfo {
|
||||
ArchiveType archiveType;
|
||||
ZipFileContents contents = ZipFileContents::NOT_A_ZIP_FILE;
|
||||
int numFiles = 0;
|
||||
int stripChars = 0; // for PSP game - how much to strip from the path.
|
||||
@@ -189,6 +195,7 @@ struct ZipFileInfo {
|
||||
std::string savedataDir;
|
||||
std::string mTime;
|
||||
std::string iniContents;
|
||||
std::string isoFilename; // Used by SevenZ only right now.
|
||||
s64 totalFileSize = 0;
|
||||
|
||||
std::string contentName;
|
||||
@@ -197,5 +204,5 @@ struct ZipFileInfo {
|
||||
ZipContainer ZipOpenPath(const Path &fileName);
|
||||
void ZipClose(ZipContainer &z);
|
||||
|
||||
bool DetectZipFileContents(const Path &fileName, ZipFileInfo *info);
|
||||
void DetectZipFileContents(zip_t *z, ZipFileInfo *info);
|
||||
bool DetectArchiveContents(VFSInterface *vfs, ZipFileInfo *info);
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "Common/System/Request.h"
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/File/VFS/SevenZipFileReader.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Core/Config.h"
|
||||
@@ -257,6 +259,25 @@ void GameManager::InstallZipContents(ZipFileTask task) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for 7z. We don't support very many scenarios here yet, but we do support ISO install.
|
||||
if (task.zipFileInfo->archiveType == ArchiveType::SevenZ) {
|
||||
Path destPath = task.destination;
|
||||
g_OSD.SetProgressBar("install", di->T("Installing..."), 0.0f, 0.0f, 0.0f, 0.1f);
|
||||
VFSInterface *reader = SevenZipFileReader::Create(task.fileName, "", true);
|
||||
// TODO: We need streaming reads here.
|
||||
size_t size;
|
||||
u8 *data = reader->ReadFile(task.zipFileInfo->isoFilename, &size);
|
||||
|
||||
Path fn(task.zipFileInfo->isoFilename);
|
||||
Path destFile = destPath / fn.GetFilename();
|
||||
|
||||
File::WriteDataToFile(false, data, size, destFile);
|
||||
g_OSD.RemoveProgressBar("install", true, 0.5f);
|
||||
installProgress_ = 1.0f;
|
||||
InstallDone();
|
||||
return;
|
||||
}
|
||||
|
||||
int error = 0;
|
||||
|
||||
ZipContainer z = ZipOpenPath(task.fileName);
|
||||
@@ -739,7 +760,9 @@ bool GameManager::InstallZipOnThread(ZipFileTask task) {
|
||||
return false;
|
||||
}
|
||||
|
||||
installThread_ = std::thread(std::bind(&GameManager::InstallZipContents, this, task));
|
||||
installThread_ = std::thread([this, task]() {
|
||||
InstallZipContents(task);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -751,7 +774,9 @@ bool GameManager::UninstallGameOnThread(const std::string &name) {
|
||||
if (InstallInProgress() || installDonePending_ || curDownload_.get() != nullptr) {
|
||||
return false;
|
||||
}
|
||||
installThread_ = std::thread(std::bind(&GameManager::UninstallGame, this, name));
|
||||
installThread_ = std::thread([this, name]() {
|
||||
UninstallGame(name);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+16
-4
@@ -24,6 +24,8 @@
|
||||
#include "Common/Data/Text/I18n.h"
|
||||
#include "Common/Data/Text/Parsers.h"
|
||||
#include "Common/Data/Format/IniFile.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/File/VFS/SevenZipFileReader.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/System.h"
|
||||
@@ -40,15 +42,25 @@
|
||||
|
||||
InstallZipScreen::InstallZipScreen(const Path &zipPath) : UITwoPaneBaseDialogScreen(Path(), TwoPaneFlags::SettingsToTheRight | TwoPaneFlags::ContentsCanScroll), zipPath_(zipPath) {
|
||||
g_GameManager.ResetInstallError();
|
||||
ZipContainer zipFile = ZipOpenPath(zipPath_);
|
||||
if (zipFile) {
|
||||
DetectZipFileContents(zipFile, &zipFileInfo_); // Even if this fails, it sets zipInfo->contents.
|
||||
ZipClose(zipFile);
|
||||
|
||||
if (zipPath.GetFileExtension() == ".7z") {
|
||||
SevenZipFileReader *sevenZipFile = SevenZipFileReader::Create(zipPath, "");
|
||||
DetectArchiveContents(sevenZipFile, &zipFileInfo_); // Even if this fails, it sets zipInfo->contents.
|
||||
delete sevenZipFile;
|
||||
} else {
|
||||
ZipContainer zipFile = ZipOpenPath(zipPath_);
|
||||
if (zipFile) {
|
||||
DetectZipFileContents(zipFile, &zipFileInfo_); // Even if this fails, it sets zipInfo->contents.
|
||||
ZipClose(zipFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view InstallZipScreen::GetTitle() const {
|
||||
auto iz = GetI18NCategory(I18NCat::INSTALLZIP);
|
||||
if (zipFileInfo_.archiveType == ArchiveType::SevenZ) {
|
||||
return iz->T("7z file");
|
||||
}
|
||||
return iz->T("ZIP file");
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -75,7 +75,8 @@
|
||||
bool MainScreen::showHomebrewTab = false;
|
||||
|
||||
static void LaunchFile(ScreenManager *screenManager, Screen *currentScreen, const Path &path) {
|
||||
if (path.GetFileExtension() == ".zip") {
|
||||
std::string extension = path.GetFileExtension();
|
||||
if (extension == ".zip" || extension == ".7z") {
|
||||
// If is a zip file, we have a screen for that.
|
||||
screenManager->push(new InstallZipScreen(path));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user