示例#1
0
int main(int argc, char **argv) {
	int ret = EXIT_SUCCESS;
	int opt;
	kga_init();
	set_signal_handler(SIGHUP, interrupted);
	set_signal_handler(SIGINT, interrupted);
	set_signal_handler(SIGTERM, interrupted);
	try_scope {
		while ((opt = getopt(argc, argv, "r:d:ti")) != -1) {
			switch(opt) {
			case 'i':
				pkg_confirm = common_confirm;
				break;
			case 'r':
				root = optarg;
				break;
			case 'd':
				db_path = optarg;
				break;
			default:
				throw(pkg_main_incorrect_cmd, 1, "unknown option", NULL);
				break;
			};
		};
		int real_argc = argc - optind;
		char **real_argv = &argv[optind];
		if (!real_argc) {
			throw(pkg_main_incorrect_cmd, 1, "no subcommand", NULL);
		} else if (!strcmp(real_argv[0], "install")) {
			if (real_argc != 2) {
				throw(pkg_main_incorrect_cmd, 1, "incorrect subcommand", NULL);
			};
			pkg_install(real_argv[1], root, db_path, 0, stderr);
		} else if (!strcmp(real_argv[0], "upgrade")) {
			if (real_argc != 2) {
				throw(pkg_main_incorrect_cmd, 1, "incorrect subcommand", NULL);
			};
			pkg_install(real_argv[1], root, db_path, PKG_UPGRADE, stderr);
		} else if (!strcmp(real_argv[0], "drop")) {
			if (real_argc < 2 || real_argc > 3) {
				throw(pkg_main_incorrect_cmd, 1, "incorrect subcommand", NULL);
			};
			char *slash;
			if ((slash = strchr(real_argv[1], '/'))) {
				*slash = '\0';
				pkg_drop(root, db_path, real_argv[1], &slash[1], stderr);
				
			} else {
				pkg_drop(root, db_path, real_argv[1], real_argc == 2 ? NULL : real_argv[2], stderr);
			}
		} else {
			throw(pkg_main_incorrect_cmd, 1, "unknown subcommand", NULL);
		};
	};
	catch {
		if (exception()->type == &pkg_main_incorrect_cmd) {
示例#2
0
void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event))
{
	const bool paused = Emu.Pause();

	wxFileDialog ctrl(this, L"Select PKG", wxEmptyString, wxEmptyString, "PKG files (*.pkg)|*.pkg|All files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
	
	if (ctrl.ShowModal() == wxID_CANCEL)
	{
		if (paused) Emu.Resume();
		return;
	}

	Emu.Stop();

	// Open PKG file
	fs::file pkg_f(ctrl.GetPath().ToStdString());

	if (!pkg_f || pkg_f.size() < 64)
	{
		LOG_ERROR(LOADER, "PKG: Failed to open %s", ctrl.GetPath().ToStdString());
		return;
	}

	// Get title ID
	std::vector<char> title_id(9);
	pkg_f.seek(55);
	pkg_f.read(title_id);
	pkg_f.seek(0);

	// Get full path
	const auto& local_path = Emu.GetGameDir() + std::string(std::begin(title_id), std::end(title_id));

	if (!fs::create_dir(local_path))
	{
		if (fs::is_dir(local_path))
		{
			if (wxMessageDialog(this, "Another installation found. Do you want to overwrite it?", "PKG Decrypter / Installer", wxYES_NO | wxCENTRE).ShowModal() != wxID_YES)
			{
				LOG_ERROR(LOADER, "PKG: Cancelled installation to existing directory %s", local_path);
				return;
			}
		}
		else
		{
			LOG_ERROR(LOADER, "PKG: Could not create the installation directory %s", local_path);
			return;
		}
	}

	wxProgressDialog pdlg("PKG Installer", "Please wait, unpacking...", 1000, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);

	// Synchronization variable
	atomic_t<double> progress(0.);
	{
		// Run PKG unpacking asynchronously
		scope_thread worker("PKG Installer", [&]
		{
			if (pkg_install(pkg_f, local_path + '/', progress))
			{
				progress = 1.;
				return_;
			}

			// TODO: Ask user to delete files on cancellation/failure?
			progress = -1.;
		});

		// Wait for the completion
		while (std::this_thread::sleep_for(5ms), std::abs(progress) < 1.)
		{
			// Update progress window
			if (!pdlg.Update(static_cast<int>(progress * pdlg.GetRange())))
			{
				// Installation cancelled (signal with negative value)
				progress -= 1.;
				break;
			}
		}
		
		if (progress > 0.)
		{
			pdlg.Update(pdlg.GetRange());
			std::this_thread::sleep_for(100ms);
		}
	}

	pdlg.Close();

	if (progress >= 1.)
	{
		// Refresh game list
		m_game_viewer->Refresh();
	}
}
示例#3
0
void MainFrame::InstallPkg(wxCommandEvent& WXUNUSED(event))
{
	const bool was_running = Emu.Pause();

	wxFileDialog ctrl(this, L"Select PKG", wxEmptyString, wxEmptyString, "PKG files (*.pkg)|*.pkg|All files (*.*)|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
	
	if (ctrl.ShowModal() == wxID_CANCEL)
	{
		if (was_running) Emu.Resume();
		return;
	}

	Emu.Stop();

	Emu.GetVFS().Init("/");
	std::string local_path;
	Emu.GetVFS().GetDevice("/dev_hdd0/game/", local_path);

	// Open PKG file
	fs::file pkg_f(ctrl.GetPath().ToStdString());

	// Open file mapping (test)
	fs::file_ptr pkg_ptr(pkg_f);

	if (!pkg_f || !pkg_ptr)
	{
		LOG_ERROR(LOADER, "PKG: Failed to open %s", ctrl.GetPath().ToStdString());
		return;
	}

	// Append title ID to the path
	local_path += '/';
	local_path += { pkg_ptr + 55, 9 };

	if (!fs::create_dir(local_path))
	{
		if (fs::is_dir(local_path))
		{
			if (wxMessageDialog(this, "Another installation found. Do you want to overwrite it?", "PKG Decrypter / Installer", wxYES_NO | wxCENTRE).ShowModal() != wxID_YES)
			{
				LOG_ERROR(LOADER, "PKG: Cancelled installation to existing directory %s", local_path);
				return;
			}
		}
		else
		{
			LOG_ERROR(LOADER, "PKG: Could not create the installation directory %s", local_path);
			return;
		}
	}

	wxProgressDialog pdlg("PKG Decrypter / Installer", "Please wait, unpacking...", 1000, this, wxPD_AUTO_HIDE | wxPD_APP_MODAL);

	volatile f64 progress = 0.0;

	// Run PKG unpacking asynchronously
	auto result = std::async(std::launch::async, WRAP_EXPR(pkg_install(pkg_f, local_path + "/", progress)));

	// Wait for the completion
	while (result.wait_for(15ms) != std::future_status::ready)
	{
		// Update progress window
		pdlg.Update(progress * pdlg.GetRange());

		// Update main frame
		Update();
		wxGetApp().ProcessPendingEvents();
	}

	pdlg.Close();

	if (result.get())
	{
		LOG_SUCCESS(LOADER, "PKG: Package successfully installed in %s", local_path);

		// Refresh game list
		m_game_viewer->Refresh();
	}
}