diff --git a/CMakeLists.txt b/CMakeLists.txt index 0359246c8..13204f479 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,8 +678,6 @@ set(CORE src/core/aerolib/stubs.cpp src/core/file_format/trp.h src/core/file_sys/fs.cpp src/core/file_sys/fs.h - src/core/loader.cpp - src/core/loader.h src/core/loader/dwarf.cpp src/core/loader/dwarf.h src/core/loader/elf.cpp @@ -969,8 +967,6 @@ set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/game_grid_frame.h src/qt_gui/game_install_dialog.cpp src/qt_gui/game_install_dialog.h - src/qt_gui/install_dir_select.cpp - src/qt_gui/install_dir_select.h src/qt_gui/trophy_viewer.cpp src/qt_gui/trophy_viewer.h src/qt_gui/elf_viewer.cpp diff --git a/documents/Quickstart/2.png b/documents/Quickstart/2.png deleted file mode 100644 index 7e5bdfb15..000000000 Binary files a/documents/Quickstart/2.png and /dev/null differ diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md index 2f2751887..9c6bc5a6f 100644 --- a/documents/Quickstart/Quickstart.md +++ b/documents/Quickstart/Quickstart.md @@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later - [**RAM**](#ram) - [**OS**](#os) - [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4) -- [**Install PKG files (Games and Updates)**](#install-pkg-files) - [**Configure the emulator**](#configure-the-emulator) ## Minimum PC requirements @@ -48,13 +47,7 @@ SPDX-License-Identifier: GPL-2.0-or-later 2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder. -3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that shadPS4 can use to install your PKG files to. - -## Install PKG files - -To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application. - - +3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that contains your dumped games. ## Configure the emulator diff --git a/documents/building-linux.md b/documents/building-linux.md index 18ddab0c6..cdc8ba12f 100644 --- a/documents/building-linux.md +++ b/documents/building-linux.md @@ -108,7 +108,7 @@ Now run the emulator. If Qt was enabled at configure time: ./build/shadps4 ``` -Otherwise, specify the path to your PKG's boot file: +Otherwise, specify the path to your game's boot file: ```bash ./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin diff --git a/src/common/config.cpp b/src/common/config.cpp index b113ac0ef..8ead58686 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -98,7 +98,6 @@ u32 m_slider_pos_grid = 0; u32 m_table_mode = 0; u32 m_window_size_W = 1280; u32 m_window_size_H = 720; -std::vector m_pkg_viewer; std::vector m_elf_viewer; std::vector m_recent_files; std::string emulator_language = "en_US"; @@ -601,11 +600,6 @@ void setMainWindowHeight(u32 height) { m_window_size_H = height; } -void setPkgViewer(const std::vector& pkgList) { - m_pkg_viewer.resize(pkgList.size()); - m_pkg_viewer = pkgList; -} - void setElfViewer(const std::vector& elfList) { m_elf_viewer.resize(elfList.size()); m_elf_viewer = elfList; @@ -709,10 +703,6 @@ u32 getMainWindowHeight() { return m_window_size_H; } -std::vector getPkgViewer() { - return m_pkg_viewer; -} - std::vector getElfViewer() { return m_elf_viewer; } @@ -886,7 +876,6 @@ void load(const std::filesystem::path& path) { main_window_geometry_y = toml::find_or(gui, "geometry_y", 0); main_window_geometry_w = toml::find_or(gui, "geometry_w", 0); main_window_geometry_h = toml::find_or(gui, "geometry_h", 0); - m_pkg_viewer = toml::find_or>(gui, "pkgDirs", {}); m_elf_viewer = toml::find_or>(gui, "elfDirs", {}); m_recent_files = toml::find_or>(gui, "recentFiles", {}); m_table_mode = toml::find_or(gui, "gameTableMode", 0); @@ -1105,7 +1094,6 @@ void saveMainWindow(const std::filesystem::path& path) { data["GUI"]["geometry_y"] = main_window_geometry_y; data["GUI"]["geometry_w"] = main_window_geometry_w; data["GUI"]["geometry_h"] = main_window_geometry_h; - data["GUI"]["pkgDirs"] = m_pkg_viewer; data["GUI"]["elfDirs"] = m_elf_viewer; data["GUI"]["recentFiles"] = m_recent_files; diff --git a/src/common/config.h b/src/common/config.h index 3a0bf252c..d040aa337 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -154,7 +154,6 @@ void setSliderPositionGrid(u32 pos); void setTableMode(u32 mode); void setMainWindowWidth(u32 width); void setMainWindowHeight(u32 height); -void setPkgViewer(const std::vector& pkgList); void setElfViewer(const std::vector& elfList); void setRecentFiles(const std::vector& recentFiles); void setEmulatorLanguage(std::string language); @@ -174,7 +173,6 @@ u32 getSliderPositionGrid(); u32 getTableMode(); u32 getMainWindowWidth(); u32 getMainWindowHeight(); -std::vector getPkgViewer(); std::vector getElfViewer(); std::vector getRecentFiles(); std::string getEmulatorLanguage(); diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp deleted file mode 100644 index ecc5f10a4..000000000 --- a/src/core/file_format/pkg.cpp +++ /dev/null @@ -1,473 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include "common/io_file.h" -#include "common/logging/formatter.h" -#include "core/file_format/pkg.h" -#include "core/file_format/pkg_type.h" - -static void DecompressPFSC(std::span compressed_data, std::span decompressed_data) { - z_stream decompressStream; - decompressStream.zalloc = Z_NULL; - decompressStream.zfree = Z_NULL; - decompressStream.opaque = Z_NULL; - - if (inflateInit(&decompressStream) != Z_OK) { - // std::cerr << "Error initializing zlib for deflation." << std::endl; - } - - decompressStream.avail_in = compressed_data.size(); - decompressStream.next_in = reinterpret_cast(compressed_data.data()); - decompressStream.avail_out = decompressed_data.size(); - decompressStream.next_out = reinterpret_cast(decompressed_data.data()); - - if (inflate(&decompressStream, Z_FINISH)) { - } - if (inflateEnd(&decompressStream) != Z_OK) { - // std::cerr << "Error ending zlib inflate" << std::endl; - } -} - -u32 GetPFSCOffset(std::span pfs_image) { - static constexpr u32 PfscMagic = 0x43534650; - u32 value; - for (u32 i = 0x20000; i < pfs_image.size(); i += 0x10000) { - std::memcpy(&value, &pfs_image[i], sizeof(u32)); - if (value == PfscMagic) - return i; - } - return -1; -} - -PKG::PKG() = default; - -PKG::~PKG() = default; - -bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) { - Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) { - return false; - } - pkgSize = file.GetSize(); - - file.Read(pkgheader); - if (pkgheader.magic != 0x7F434E54) - return false; - - for (const auto& flag : flagNames) { - if (isFlagSet(pkgheader.pkg_content_flags, flag.first)) { - if (!pkgFlags.empty()) - pkgFlags += (", "); - pkgFlags += (flag.second); - } - } - - // Find title id it is part of pkg_content_id starting at offset 0x40 - file.Seek(0x47); // skip first 7 characters of content_id - file.Read(pkgTitleID); - - u32 offset = pkgheader.pkg_table_entry_offset; - u32 n_files = pkgheader.pkg_table_entry_count; - - if (!file.Seek(offset)) { - failreason = "Failed to seek to PKG table entry offset"; - return false; - } - - for (int i = 0; i < n_files; i++) { - PKGEntry entry{}; - file.Read(entry.id); - file.Read(entry.filename_offset); - file.Read(entry.flags1); - file.Read(entry.flags2); - file.Read(entry.offset); - file.Read(entry.size); - file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); - - // Try to figure out the name - const auto name = GetEntryNameByType(entry.id); - if (name == "param.sfo") { - sfo.clear(); - if (!file.Seek(entry.offset)) { - failreason = "Failed to seek to param.sfo offset"; - return false; - } - sfo.resize(entry.size); - file.ReadRaw(sfo.data(), entry.size); - } - } - file.Close(); - - return true; -} - -bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract, - std::string& failreason) { - extract_path = extract; - pkgpath = filepath; - Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read); - if (!file.IsOpen()) { - return false; - } - pkgSize = file.GetSize(); - file.ReadRaw(&pkgheader, sizeof(PKGHeader)); - - if (pkgheader.magic != 0x7F434E54) - return false; - - if (pkgheader.pkg_size > pkgSize) { - failreason = "PKG file size is different"; - return false; - } - if ((pkgheader.pkg_content_size + pkgheader.pkg_content_offset) > pkgheader.pkg_size) { - failreason = "Content size is bigger than pkg size"; - return false; - } - - u32 offset = pkgheader.pkg_table_entry_offset; - u32 n_files = pkgheader.pkg_table_entry_count; - - std::array concatenated_ivkey_dk3; - std::array seed_digest; - std::array, 7> digest1; - std::array, 7> key1; - std::array imgkeydata; - - if (!file.Seek(offset)) { - failreason = "Failed to seek to PKG table entry offset"; - return false; - } - - for (int i = 0; i < n_files; i++) { - PKGEntry entry{}; - file.Read(entry.id); - file.Read(entry.filename_offset); - file.Read(entry.flags1); - file.Read(entry.flags2); - file.Read(entry.offset); - file.Read(entry.size); - file.Seek(8, Common::FS::SeekOrigin::CurrentPosition); - - auto currentPos = file.Tell(); - - // Try to figure out the name - const auto name = GetEntryNameByType(entry.id); - const auto filepath = extract_path / "sce_sys" / name; - std::filesystem::create_directories(filepath.parent_path()); - - if (name.empty()) { - // Just print with id - Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id), - Common::FS::FileAccessMode::Write); - if (!file.Seek(entry.offset)) { - failreason = "Failed to seek to PKG entry offset"; - return false; - } - - std::vector data; - data.resize(entry.size); - file.ReadRaw(data.data(), entry.size); - out.WriteRaw(data.data(), entry.size); - out.Close(); - - file.Seek(currentPos); - continue; - } - - if (entry.id == 0x1) { // DIGESTS, seek; - // file.Seek(entry.offset, fsSeekSet); - } else if (entry.id == 0x10) { // ENTRY_KEYS, seek; - file.Seek(entry.offset); - file.Read(seed_digest); - - for (int i = 0; i < 7; i++) { - file.Read(digest1[i]); - } - - for (int i = 0; i < 7; i++) { - file.Read(key1[i]); - } - - PKG::crypto.RSA2048Decrypt(dk3_, key1[3], true); // decrypt DK3 - } else if (entry.id == 0x20) { // IMAGE_KEY, seek; IV_KEY - file.Seek(entry.offset); - file.Read(imgkeydata); - - // The Concatenated iv + dk3 imagekey for HASH256 - std::memcpy(concatenated_ivkey_dk3.data(), &entry, sizeof(entry)); - std::memcpy(concatenated_ivkey_dk3.data() + sizeof(entry), dk3_.data(), sizeof(dk3_)); - - PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3, ivKey); // ivkey_ - // imgkey_ to use for last step to get ekpfs - PKG::crypto.aesCbcCfb128Decrypt(ivKey, imgkeydata, imgKey); - // ekpfs key to get data and tweak keys. - PKG::crypto.RSA2048Decrypt(ekpfsKey, imgKey, false); - } else if (entry.id == 0x80) { - // GENERAL_DIGESTS, seek; - // file.Seek(entry.offset, fsSeekSet); - } - - Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write); - if (!file.Seek(entry.offset)) { - failreason = "Failed to seek to PKG entry offset"; - return false; - } - - std::vector data; - data.resize(entry.size); - file.ReadRaw(data.data(), entry.size); - out.WriteRaw(data.data(), entry.size); - out.Close(); - - // Decrypt Np stuff and overwrite. - if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 || - entry.id == 0x403) { // somehow 0x401 is not decrypting - decNp.resize(entry.size); - if (!file.Seek(entry.offset)) { - failreason = "Failed to seek to PKG entry offset"; - return false; - } - - std::vector data; - data.resize(entry.size); - file.ReadRaw(data.data(), entry.size); - - std::span cipherNp(data.data(), entry.size); - std::array concatenated_ivkey_dk3_; - std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry)); - std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_)); - PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3_, ivKey); - PKG::crypto.aesCbcCfb128DecryptEntry(ivKey, cipherNp, decNp); - - Common::FS::IOFile out(extract_path / "sce_sys" / name, - Common::FS::FileAccessMode::Write); - out.Write(decNp); - out.Close(); - } - - file.Seek(currentPos); - } - - // Read the seed - std::array seed; - if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) { - failreason = "Failed to seek to PFS image offset"; - return false; - } - file.Read(seed); - - // Get data and tweak keys. - PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey); - const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok. - - int num_blocks = 0; - std::vector pfsc(length); - if (length != 0) { - // Read encrypted pfs_image - std::vector pfs_encrypted(length); - file.Seek(pkgheader.pfs_image_offset); - file.Read(pfs_encrypted); - file.Close(); - // Decrypt the pfs_image. - std::vector pfs_decrypted(length); - PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0); - - // Retrieve PFSC from decrypted pfs_image. - pfsc_offset = GetPFSCOffset(pfs_decrypted); - std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset); - - PFSCHdr pfsChdr; - std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr)); - - num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2); - sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset. - - for (int i = 0; i < num_blocks + 1; i++) { - std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8); - } - } - - u32 ent_size = 0; - u32 ndinode = 0; - int ndinode_counter = 0; - bool dinode_reached = false; - bool uroot_reached = false; - std::vector compressedData; - std::vector decompressedData(0x10000); - - // Get iNdoes and Dirents. - for (int i = 0; i < num_blocks; i++) { - const u64 sectorOffset = sectorMap[i]; - const u64 sectorSize = sectorMap[i + 1] - sectorOffset; - - compressedData.resize(sectorSize); - std::memcpy(compressedData.data(), pfsc.data() + sectorOffset, sectorSize); - - if (sectorSize == 0x10000) // Uncompressed data - std::memcpy(decompressedData.data(), compressedData.data(), 0x10000); - else if (sectorSize < 0x10000) // Compressed data - DecompressPFSC(compressedData, decompressedData); - - if (i == 0) { - std::memcpy(&ndinode, decompressedData.data() + 0x30, 4); // number of folders and files - } - - int occupied_blocks = - (ndinode * 0xA8) / 0x10000; // how many blocks(0x10000) are taken by iNodes. - if (((ndinode * 0xA8) % 0x10000) != 0) - occupied_blocks += 1; - - if (i >= 1 && i <= occupied_blocks) { // Get all iNodes, gives type, file size and location. - for (int p = 0; p < 0x10000; p += 0xA8) { - Inode node; - std::memcpy(&node, &decompressedData[p], sizeof(node)); - if (node.Mode == 0) { - break; - } - iNodeBuf.push_back(node); - } - } - - // let's deal with the root/uroot entries here. - // Sometimes it's more than 2 entries (Tomb Raider Remastered) - const std::string_view flat_path_table(&decompressedData[0x10], 15); - if (flat_path_table == "flat_path_table") { - uroot_reached = true; - } - - if (uroot_reached) { - for (int i = 0; i < 0x10000; i += ent_size) { - Dirent dirent; - std::memcpy(&dirent, &decompressedData[i], sizeof(dirent)); - ent_size = dirent.entsize; - if (dirent.ino != 0) { - ndinode_counter++; - } else { - // Set the the folder according to the current inode. - // Can be 2 or more (rarely) - auto parent_path = extract_path.parent_path(); - auto title_id = GetTitleID(); - - if (parent_path.filename() != title_id && - !fmt::UTF(extract_path.u8string()).data.ends_with("-patch")) { - extractPaths[ndinode_counter] = parent_path / title_id; - } else { - // DLCs path has different structure - extractPaths[ndinode_counter] = extract_path; - } - uroot_reached = false; - break; - } - } - } - - const char dot = decompressedData[0x10]; - const std::string_view dotdot(&decompressedData[0x28], 2); - if (dot == '.' && dotdot == "..") { - dinode_reached = true; - } - - // Get folder and file names. - bool end_reached = false; - if (dinode_reached) { - for (int j = 0; j < 0x10000; j += ent_size) { // Skip the first parent and child. - Dirent dirent; - std::memcpy(&dirent, &decompressedData[j], sizeof(dirent)); - - // Stop here and continue the main loop - if (dirent.ino == 0) { - break; - } - - ent_size = dirent.entsize; - auto& table = fsTable.emplace_back(); - table.name = std::string(dirent.name, dirent.namelen); - table.inode = dirent.ino; - table.type = dirent.type; - - if (table.type == PFS_CURRENT_DIR) { - current_dir = extractPaths[table.inode]; - } - extractPaths[table.inode] = current_dir / std::filesystem::path(table.name); - - if (table.type == PFS_FILE || table.type == PFS_DIR) { - if (table.type == PFS_DIR) { // Create dirs. - std::filesystem::create_directory(extractPaths[table.inode]); - } - ndinode_counter++; - if ((ndinode_counter + 1) == ndinode) // 1 for the image itself (root). - end_reached = true; - } - } - if (end_reached) { - break; - } - } - } - return true; -} - -void PKG::ExtractFiles(const int index) { - int inode_number = fsTable[index].inode; - int inode_type = fsTable[index].type; - std::string inode_name = fsTable[index].name; - - if (inode_type == PFS_FILE) { - int sector_loc = iNodeBuf[inode_number].loc; - int nblocks = iNodeBuf[inode_number].Blocks; - int bsize = iNodeBuf[inode_number].Size; - - Common::FS::IOFile inflated; - inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write); - - Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict. - pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read); - - int size_decompressed = 0; - std::vector compressedData; - std::vector decompressedData(0x10000); - - u64 pfsc_buf_size = 0x11000; // extra 0x1000 - std::vector pfsc(pfsc_buf_size); - std::vector pfs_decrypted(pfsc_buf_size); - - for (int j = 0; j < nblocks; j++) { - u64 sectorOffset = - sectorMap[sector_loc + j]; // offset into PFSC_image and not pfs_image. - u64 sectorSize = sectorMap[sector_loc + j + 1] - - sectorOffset; // indicates if data is compressed or not. - u64 fileOffset = (pkgheader.pfs_image_offset + pfsc_offset + sectorOffset); - u64 currentSector1 = - (pfsc_offset + sectorOffset) / 0x1000; // block size is 0x1000 for xts decryption. - - int sectorOffsetMask = (sectorOffset + pfsc_offset) & 0xFFFFF000; - int previousData = (sectorOffset + pfsc_offset) - sectorOffsetMask; - - pkgFile.Seek(fileOffset - previousData); - pkgFile.Read(pfsc); - - PKG::crypto.decryptPFS(dataKey, tweakKey, pfsc, pfs_decrypted, currentSector1); - - compressedData.resize(sectorSize); - std::memcpy(compressedData.data(), pfs_decrypted.data() + previousData, sectorSize); - - if (sectorSize == 0x10000) // Uncompressed data - std::memcpy(decompressedData.data(), compressedData.data(), 0x10000); - else if (sectorSize < 0x10000) // Compressed data - DecompressPFSC(compressedData, decompressedData); - - size_decompressed += 0x10000; - - if (j < nblocks - 1) { - inflated.WriteRaw(decompressedData.data(), decompressedData.size()); - } else { - // This is to remove the zeros at the end of the file. - const u32 write_size = decompressedData.size() - (size_decompressed - bsize); - inflated.WriteRaw(decompressedData.data(), write_size); - } - } - pkgFile.Close(); - inflated.Close(); - } -} diff --git a/src/core/loader.cpp b/src/core/loader.cpp deleted file mode 100644 index f80bfbb81..000000000 --- a/src/core/loader.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/io_file.h" -#include "common/types.h" -#include "loader.h" - -namespace Loader { - -FileTypes DetectFileType(const std::filesystem::path& filepath) { - // No file loaded - if (filepath.empty()) { - return FileTypes::Unknown; - } - Common::FS::IOFile file; - file.Open(filepath, Common::FS::FileAccessMode::Read); - file.Seek(0); - u32 magic; - file.Read(magic); - file.Close(); - switch (magic) { - case PkgMagic: - return FileTypes::Pkg; - } - return FileTypes::Unknown; -} - -} // namespace Loader diff --git a/src/core/loader.h b/src/core/loader.h deleted file mode 100644 index 608970dca..000000000 --- a/src/core/loader.h +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include - -namespace Loader { - -constexpr static u32 PkgMagic = 0x544e437f; - -enum class FileTypes { - Unknown, - Pkg, -}; - -FileTypes DetectFileType(const std::filesystem::path& filepath); -} // namespace Loader diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 0cc0e48dc..7dcb006ba 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -599,30 +598,6 @@ public: return -1; } - void RequestGameMenuPKGViewer( - const QPoint& pos, QStringList m_pkg_app_list, QTreeWidget* treeWidget, - std::function InstallDragDropPkg) { - QPoint global_pos = treeWidget->viewport()->mapToGlobal(pos); // context menu position - QTreeWidgetItem* currentItem = treeWidget->currentItem(); // current clicked item - int itemIndex = GetRowIndex(treeWidget, currentItem); // row - - QMenu menu(treeWidget); - QAction installPackage(tr("Install PKG"), treeWidget); - - menu.addAction(&installPackage); - - auto selected = menu.exec(global_pos); - if (!selected) { - return; - } - - if (selected == &installPackage) { - QStringList pkg_app_ = m_pkg_app_list[itemIndex].split(";;"); - std::filesystem::path path = Common::FS::PathFromQString(pkg_app_[9]); - InstallDragDropPkg(path, 1, 1); - } - } - private: bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) { // Load the PNG image diff --git a/src/qt_gui/install_dir_select.cpp b/src/qt_gui/install_dir_select.cpp deleted file mode 100644 index e90a10ee6..000000000 --- a/src/qt_gui/install_dir_select.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "install_dir_select.h" - -InstallDirSelect::InstallDirSelect() : selected_dir() { - auto install_dirs = Config::getGameInstallDirs(); - selected_dir = install_dirs.empty() ? "" : install_dirs.front(); - - if (!install_dirs.empty() && install_dirs.size() == 1) { - accept(); - } - - auto layout = new QVBoxLayout(this); - - layout->addWidget(SetupInstallDirList()); - layout->addStretch(); - layout->addWidget(SetupDialogActions()); - - setWindowTitle(tr("shadPS4 - Choose directory")); - setWindowIcon(QIcon(":images/shadps4.ico")); -} - -InstallDirSelect::~InstallDirSelect() {} - -QWidget* InstallDirSelect::SetupInstallDirList() { - auto group = new QGroupBox(tr("Select which directory you want to install to.")); - auto vlayout = new QVBoxLayout(); - - auto m_path_list = new QListWidget(); - QList qt_list; - for (const auto& str : Config::getGameInstallDirs()) { - QString installDirPath; - Common::FS::PathToQString(installDirPath, str); - qt_list.append(installDirPath); - } - m_path_list->insertItems(0, qt_list); - m_path_list->setSpacing(1); - - connect(m_path_list, &QListWidget::itemClicked, this, &InstallDirSelect::setSelectedDirectory); - connect(m_path_list, &QListWidget::itemActivated, this, - &InstallDirSelect::setSelectedDirectory); - - vlayout->addWidget(m_path_list); - - auto checkbox = new QCheckBox(tr("Install All Queued to Selected Folder")); - connect(checkbox, &QCheckBox::toggled, this, &InstallDirSelect::setUseForAllQueued); - vlayout->addWidget(checkbox); - - auto checkbox2 = new QCheckBox(tr("Delete PKG File on Install")); - connect(checkbox2, &QCheckBox::toggled, this, &InstallDirSelect::setDeleteFileOnInstall); - vlayout->addWidget(checkbox2); - - group->setLayout(vlayout); - return group; -} - -void InstallDirSelect::setSelectedDirectory(QListWidgetItem* item) { - if (item) { - const auto highlighted_path = Common::FS::PathFromQString(item->text()); - if (!highlighted_path.empty()) { - selected_dir = highlighted_path; - } - } -} - -void InstallDirSelect::setUseForAllQueued(bool enabled) { - use_for_all_queued = enabled; -} - -void InstallDirSelect::setDeleteFileOnInstall(bool enabled) { - delete_file_on_install = enabled; -} - -QWidget* InstallDirSelect::SetupDialogActions() { - auto actions = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - - connect(actions, &QDialogButtonBox::accepted, this, &InstallDirSelect::accept); - connect(actions, &QDialogButtonBox::rejected, this, &InstallDirSelect::reject); - - return actions; -} diff --git a/src/qt_gui/install_dir_select.h b/src/qt_gui/install_dir_select.h deleted file mode 100644 index e11cbf381..000000000 --- a/src/qt_gui/install_dir_select.h +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "common/config.h" -#include "common/path_util.h" - -class QLineEdit; - -class InstallDirSelect final : public QDialog { - Q_OBJECT - -public: - InstallDirSelect(); - ~InstallDirSelect(); - - std::filesystem::path getSelectedDirectory() { - return selected_dir; - } - - bool useForAllQueued() { - return use_for_all_queued; - } - - bool deleteFileOnInstall() { - return delete_file_on_install; - } - -private: - QWidget* SetupInstallDirList(); - QWidget* SetupDialogActions(); - void setSelectedDirectory(QListWidgetItem* item); - void setDeleteFileOnInstall(bool enabled); - void setUseForAllQueued(bool enabled); - std::filesystem::path selected_dir; - bool delete_file_on_install = false; - bool use_for_all_queued = false; -}; diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index e92676c02..5d8f8e717 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -20,9 +20,7 @@ #include "common/string_util.h" #include "common/version.h" #include "control_settings.h" -#include "core/loader.h" #include "game_install_dialog.h" -#include "install_dir_select.h" #include "kbm_gui.h" #include "main_window.h" #include "settings_dialog.h"