Added installation for additional packages to game boot

This commit is contained in:
Peter Mcteague 2017-09-13 00:49:02 +01:00 committed by Nekotekina
parent 8901cc9ae6
commit 6702c14b88
5 changed files with 141 additions and 18 deletions

View file

@ -24,6 +24,12 @@ inline void strcpy_trunc(char (&dst)[N], const char (&src)[N2])
dst[count] = '\0';
}
template <std::size_t N>
inline bool ends_with(const std::string& src, const char (&end)[N])
{
return src.size() >= N - 1 && src.compare(src.size() - (N - 1), N - 1, end, N - 1) == 0;
}
namespace fmt
{
std::string replace_first(const std::string& src, const std::string& from, const std::string& to);

View file

@ -22,6 +22,7 @@
#include "Utilities/StrUtil.h"
#include "../Crypto/unself.h"
#include "../Crypto/unpkg.h"
#include "yaml-cpp/yaml.h"
#include <thread>
@ -212,6 +213,7 @@ void Emulator::Init()
fs::create_dir(dev_hdd0 + "game/");
fs::create_dir(dev_hdd0 + "game/TEST12345/");
fs::create_dir(dev_hdd0 + "game/TEST12345/USRDIR/");
fs::create_dir(dev_hdd0 + "game/.locks/");
fs::create_dir(dev_hdd0 + "home/");
fs::create_dir(dev_hdd0 + "home/00000001/");
fs::create_dir(dev_hdd0 + "home/00000001/exdata/");
@ -223,7 +225,7 @@ void Emulator::Init()
fs::create_dir(dev_hdd1 + "game/");
fs::create_path(dev_hdd1);
fs::create_path(dev_usb);
#ifdef WITH_GDB_DEBUGGER
fxm::make<GDBDebugServer>();
#endif
@ -265,6 +267,51 @@ bool Emulator::BootGame(const std::string& path, bool direct, bool add_only)
return false;
}
bool Emulator::InstallPkg(const std::string& path)
{
LOG_SUCCESS(GENERAL, "Installing package: %s", path);
atomic_t<double> progress(0.);
int int_progress = 0;
{
// Run PKG unpacking asynchronously
scope_thread worker("PKG Installer", [&]
{
if (pkg_install(path, progress))
{
progress = 1.;
return;
}
progress = -1.;
});
// Wait for the completion
while (std::this_thread::sleep_for(5ms), std::abs(progress) < 1.)
{
// TODO: update unified progress dialog
double pval = progress;
pval < 0 ? pval += 1. : pval;
pval *= 100.;
if (static_cast<int>(pval) > int_progress)
{
int_progress = static_cast<int>(pval);
LOG_SUCCESS(GENERAL, "... %u%%", int_progress);
}
m_cb.process_events();
}
}
if (progress >= 1.)
{
return true;
}
return false;
}
std::string Emulator::GetHddDir()
{
const std::string& emu_dir_ = g_cfg.vfs.emulator_dir;
@ -297,7 +344,7 @@ void Emulator::Load(bool add_only)
{
Init();
// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations)
// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations)
YAML::Node games = YAML::Load(fs::file{fs::get_config_dir() + "/games.yml", fs::read + fs::create}.to_string());
if (!games.IsMap())
@ -453,7 +500,8 @@ void Emulator::Load(bool add_only)
}
else if (!Emu.disc.empty())
{
vfs::mount("dev_bdvd", Emu.disc);
bdvd_dir = Emu.disc;
vfs::mount("dev_bdvd", bdvd_dir);
LOG_NOTICE(LOADER, "Disk: %s", vfs::get("/dev_bdvd"));
}
else if (_cat == "DG" || _cat == "GD")
@ -468,6 +516,73 @@ void Emulator::Load(bool add_only)
return;
}
// Install PKGDIR, INSDIR, PS3_EXTRA
if (!bdvd_dir.empty())
{
const std::string ins_dir = vfs::get("/dev_bdvd/PS3_GAME/INSDIR/");
const std::string pkg_dir = vfs::get("/dev_bdvd/PS3_GAME/PKGDIR/");
const std::string extra_dir = vfs::get("/dev_bdvd/PS3_GAME/PS3_EXTRA/");
fs::file lock_file;
if (fs::is_dir(ins_dir) || fs::is_dir(pkg_dir) || fs::is_dir(extra_dir))
{
// Create lock file to prevent double installation
lock_file.open(hdd0_game + ".locks/" + m_title_id, fs::read + fs::create + fs::excl);
}
if (lock_file && fs::is_dir(ins_dir))
{
LOG_NOTICE(LOADER, "Found INSDIR: %s", ins_dir);
for (auto&& entry : fs::dir{ins_dir})
{
if (!entry.is_directory && ends_with(entry.name, ".PKG") && !InstallPkg(ins_dir + entry.name))
{
LOG_ERROR(LOADER, "Failed to install /dev_bdvd/PS3_GAME/INSDIR/%s", entry.name);
return;
}
}
}
if (lock_file && fs::is_dir(pkg_dir))
{
LOG_NOTICE(LOADER, "Found PKGDIR: %s", pkg_dir);
for (auto&& entry : fs::dir{pkg_dir})
{
if (entry.is_directory && entry.name.compare(0, 3, "PKG", 3) == 0)
{
const std::string pkg_file = pkg_dir + entry.name + "/INSTALL.PKG";
if (fs::is_file(pkg_file) && !InstallPkg(pkg_file))
{
LOG_ERROR(LOADER, "Failed to install /dev_bdvd/PS3_GAME/PKGDIR/%s/INSTALL.PKG", entry.name);
return;
}
}
}
}
if (lock_file && fs::is_dir(extra_dir))
{
LOG_NOTICE(LOADER, "Found PS3_EXTRA: %s", extra_dir);
for (auto&& entry : fs::dir{extra_dir})
{
if (entry.is_directory && entry.name[0] == 'D')
{
const std::string pkg_file = extra_dir + entry.name + "/DATA000.PKG";
if (fs::is_file(pkg_file) && !InstallPkg(pkg_file))
{
LOG_ERROR(LOADER, "Failed to install /dev_bdvd/PS3_GAME/PKGDIR/%s/DATA000.PKG", entry.name);
return;
}
}
}
}
}
// Check game updates
const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN";

View file

@ -245,6 +245,7 @@ public:
}
bool BootGame(const std::string& path, bool direct = false, bool add_only = false);
bool InstallPkg(const std::string& path);
static std::string GetHddDir();
static std::string GetLibDir();
@ -372,7 +373,7 @@ struct cfg_root : cfg::node
cfg::_int<2, 128> frames{this, "Buffer Count", 32};
} audio{this};
struct node_io : cfg::node
{
node_io(cfg::node* _this) : cfg::node(_this, "Input/Output") {}
@ -384,7 +385,7 @@ struct cfg_root : cfg::node
cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
} io{this};
struct node_sys : cfg::node
{
node_sys(cfg::node* _this) : cfg::node(_this, "System") {}
@ -392,7 +393,7 @@ struct cfg_root : cfg::node
cfg::_enum<CellSysutilLang> language{this, "Language"};
} sys{this};
struct node_net : cfg::node
{
node_net(cfg::node* _this) : cfg::node(_this, "Net") {}
@ -405,7 +406,7 @@ struct cfg_root : cfg::node
struct node_misc : cfg::node
{
node_misc(cfg::node* _this) : cfg::node(_this, "Miscellaneous") {}
cfg::_bool autostart{this, "Automatically start games after boot", true};
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"};
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" };

View file

@ -105,7 +105,7 @@ void rpcs3_app::InitializeCallbacks()
quit();
};
callbacks.call_after = [=](std::function<void()> func)
{
{
RequestCallAfter(std::move(func));
};
@ -176,7 +176,7 @@ void rpcs3_app::InitializeCallbacks()
gameWindow = ret;
return std::unique_ptr<gs_frame>(ret);
}
case video_renderer::opengl:
case video_renderer::opengl:
{
gl_gs_frame* ret = new gl_gs_frame(w, h, RPCS3MainWin->GetAppIcon(), disableMouse);
gameWindow = ret;

View file

@ -38,6 +38,7 @@
#include "Loader/PUP.h"
#include "Loader/TAR.h"
#include "Loader/PSF.h"
#include "Utilities/Thread.h"
#include "Utilities/StrUtil.h"
@ -67,7 +68,7 @@ auto Pause = []()
else if (!Emu.GetBoot().empty()) Emu.Load();
};
/* An init method is used so that RPCS3App can create the necessary connects before calling init (specifically the stylesheet connect).
/* An init method is used so that RPCS3App can create the necessary connects before calling init (specifically the stylesheet connect).
* Simplifies logic a bit.
*/
void main_window::Init()
@ -108,7 +109,7 @@ void main_window::Init()
Q_EMIT RequestGlobalStylesheetChange(guiSettings->GetCurrentStylesheetPath());
ConfigureGuiFromSettings(true);
if (!utils::has_ssse3())
{
QMessageBox::critical(this, "SSSE3 Error (with three S, not two)",
@ -252,7 +253,7 @@ void main_window::BootElf()
"SELF files (EBOOT.BIN *.self);;"
"BOOT files (*BOOT.BIN);;"
"BIN files (*.bin);;"
"All files (*.*)"),
"All files (*.*)"),
Q_NULLPTR, QFileDialog::DontResolveSymlinks);
if (filePath == NULL)
@ -603,7 +604,7 @@ void main_window::DecryptSPRXLibraries()
LOG_NOTICE(GENERAL, "Finished decrypting all SPRX libraries.");
}
/** Needed so that when a backup occurs of window state in guisettings, the state is current.
/** Needed so that when a backup occurs of window state in guisettings, the state is current.
* Also, so that on close, the window state is preserved.
*/
void main_window::SaveWindowState()
@ -622,7 +623,7 @@ void main_window::SaveWindowState()
void main_window::RepaintThumbnailIcons()
{
QColor newColor = gui::get_Label_Color("thumbnail_icon_color");
auto icon = [&newColor](const QString& path)
{
return gui_settings::colorizedIcon(QPixmap::fromImage(gui_settings::GetOpaqueImageArea(path)), gui::mw_tool_icon_color, newColor);
@ -918,7 +919,7 @@ QAction* main_window::CreateRecentAction(const q_string_pair& entry, const uint&
act->setData(entry.first);
act->setToolTip(entry.second);
act->setShortcut(tr("Ctrl+%1").arg(sc_idx));
// truncate if too long
if (shown_name.length() > 60)
{
@ -977,7 +978,7 @@ void main_window::AddRecentAction(const q_string_pair& entry)
m_rg_entries.prepend(entry);
m_recentGameActs.prepend(act);
}
// refill menu with actions
for (int i = 0; i < m_recentGameActs.count(); i++)
{
@ -1040,7 +1041,7 @@ void main_window::CreateActions()
ui->toolbar_start->setEnabled(false);
ui->toolbar_stop->setEnabled(false);
m_categoryVisibleActGroup = new QActionGroup(this);
m_categoryVisibleActGroup = new QActionGroup(this);
m_categoryVisibleActGroup->addAction(ui->showCatHDDGameAct);
m_categoryVisibleActGroup->addAction(ui->showCatDiscGameAct);
m_categoryVisibleActGroup->addAction(ui->showCatHomeAct);
@ -1530,7 +1531,7 @@ void main_window::mouseDoubleClickEvent(QMouseEvent *event)
}
}
/** Override the Qt close event to have the emulator stop and the application die. May add a warning dialog in future.
/** Override the Qt close event to have the emulator stop and the application die. May add a warning dialog in future.
*/
void main_window::closeEvent(QCloseEvent* closeEvent)
{