2020-12-05 13:08:24 +01:00
|
|
|
|
#include "stdafx.h"
|
2020-02-15 23:36:20 +01:00
|
|
|
|
#include "VFS.h"
|
2017-03-29 01:54:05 +02:00
|
|
|
|
#include "Utilities/bin_patch.h"
|
2018-07-27 21:07:34 +02:00
|
|
|
|
#include "Emu/Memory/vm.h"
|
2014-06-02 19:27:24 +02:00
|
|
|
|
#include "Emu/System.h"
|
2021-04-21 22:12:21 +02:00
|
|
|
|
#include "Emu/system_progress.hpp"
|
|
|
|
|
|
#include "Emu/system_utils.hpp"
|
2020-11-19 09:12:59 +01:00
|
|
|
|
#include "Emu/perf_meter.hpp"
|
2022-03-11 21:08:44 +01:00
|
|
|
|
#include "Emu/perf_monitor.hpp"
|
2021-09-23 20:12:06 +02:00
|
|
|
|
#include "Emu/vfs_config.h"
|
2022-06-18 21:30:38 +02:00
|
|
|
|
#include "Emu/IPC_config.h"
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
2020-12-12 12:24:01 +01:00
|
|
|
|
#include "Emu/Cell/ErrorCodes.h"
|
2012-11-15 00:39:56 +01:00
|
|
|
|
#include "Emu/Cell/PPUThread.h"
|
2017-10-05 23:24:50 +02:00
|
|
|
|
#include "Emu/Cell/PPUDisAsm.h"
|
2018-03-17 18:41:35 +01:00
|
|
|
|
#include "Emu/Cell/PPUAnalyser.h"
|
2012-11-15 00:39:56 +01:00
|
|
|
|
#include "Emu/Cell/SPUThread.h"
|
2021-01-22 09:11:54 +01:00
|
|
|
|
#include "Emu/RSX/RSXThread.h"
|
2019-11-01 20:21:15 +01:00
|
|
|
|
#include "Emu/Cell/lv2/sys_process.h"
|
2016-04-14 00:59:00 +02:00
|
|
|
|
#include "Emu/Cell/lv2/sys_sync.h"
|
2018-03-17 18:41:35 +01:00
|
|
|
|
#include "Emu/Cell/lv2/sys_prx.h"
|
2021-01-30 15:25:21 +01:00
|
|
|
|
#include "Emu/Cell/lv2/sys_overlay.h"
|
2022-07-11 09:53:29 +02:00
|
|
|
|
#include "Emu/Cell/lv2/sys_spu.h"
|
2022-04-09 23:28:52 +02:00
|
|
|
|
#include "Emu/Cell/Modules/cellGame.h"
|
2013-12-08 17:54:45 +01:00
|
|
|
|
|
2020-02-14 01:08:02 +01:00
|
|
|
|
#include "Emu/title.h"
|
2014-08-26 01:55:37 +02:00
|
|
|
|
#include "Emu/IdManager.h"
|
2018-05-13 11:18:05 +02:00
|
|
|
|
#include "Emu/RSX/Capture/rsx_replay.h"
|
2014-08-26 01:55:37 +02:00
|
|
|
|
|
2014-08-09 18:04:53 +02:00
|
|
|
|
#include "Loader/PSF.h"
|
2022-07-04 15:02:17 +02:00
|
|
|
|
#include "Loader/TAR.h"
|
2016-04-14 00:59:00 +02:00
|
|
|
|
#include "Loader/ELF.h"
|
2022-06-21 22:13:22 +02:00
|
|
|
|
#include "Loader/disc.h"
|
2014-08-09 17:16:21 +02:00
|
|
|
|
|
2016-04-27 00:27:24 +02:00
|
|
|
|
#include "Utilities/StrUtil.h"
|
|
|
|
|
|
|
2014-03-03 05:48:07 +01:00
|
|
|
|
#include "../Crypto/unself.h"
|
2020-03-09 17:18:39 +01:00
|
|
|
|
#include "util/yaml.hpp"
|
2020-03-28 15:28:23 +01:00
|
|
|
|
#include "util/logs.hpp"
|
2021-06-01 18:13:05 +02:00
|
|
|
|
#include "util/serialization.hpp"
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
#include <memory>
|
2019-06-01 00:12:30 +02:00
|
|
|
|
#include <regex>
|
2022-07-04 15:02:17 +02:00
|
|
|
|
#include <optional>
|
2016-05-13 16:01:48 +02:00
|
|
|
|
|
2019-01-26 21:15:45 +01:00
|
|
|
|
#include "Utilities/JIT.h"
|
2018-06-13 13:54:16 +02:00
|
|
|
|
|
2019-10-12 14:40:47 +02:00
|
|
|
|
#include "display_sleep_control.h"
|
|
|
|
|
|
|
2022-06-18 21:30:38 +02:00
|
|
|
|
#include "Emu/IPC_socket.h"
|
|
|
|
|
|
|
2021-11-13 16:11:49 +01:00
|
|
|
|
#if defined(HAVE_VULKAN)
|
2018-05-18 21:37:20 +02:00
|
|
|
|
#include "Emu/RSX/VK/VulkanAPI.h"
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2020-02-01 08:43:43 +01:00
|
|
|
|
LOG_CHANNEL(sys_log, "SYS");
|
2020-01-31 14:43:59 +01:00
|
|
|
|
|
2021-02-03 19:14:31 +01:00
|
|
|
|
// Preallocate 32 MiB
|
|
|
|
|
|
stx::manual_typemap<void, 0x20'00000, 128> g_fixed_typemap;
|
2019-08-20 03:49:22 +02:00
|
|
|
|
|
2022-04-24 14:35:26 +02:00
|
|
|
|
bool g_log_all_errors = false;
|
|
|
|
|
|
|
2020-10-30 23:52:24 +01:00
|
|
|
|
bool g_use_rtm = false;
|
|
|
|
|
|
u64 g_rtm_tx_limit1 = 0;
|
|
|
|
|
|
u64 g_rtm_tx_limit2 = 0;
|
2018-05-14 22:07:36 +02:00
|
|
|
|
|
2016-06-02 17:16:01 +02:00
|
|
|
|
std::string g_cfg_defaults;
|
2015-12-16 20:50:45 +01:00
|
|
|
|
|
2020-06-01 01:27:33 +02:00
|
|
|
|
atomic_t<u64> g_watchdog_hold_ctr{0};
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
extern bool ppu_load_exec(const ppu_exec_object&, utils::serial* = nullptr);
|
2016-07-09 00:36:42 +02:00
|
|
|
|
extern void spu_load_exec(const spu_exec_object&);
|
2022-04-27 18:46:09 +02:00
|
|
|
|
extern void spu_load_rel_exec(const spu_rel_object&);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_module*>* loaded_prx);
|
2021-01-30 14:08:22 +01:00
|
|
|
|
extern bool ppu_initialize(const ppu_module&, bool = false);
|
2021-01-27 14:08:43 +01:00
|
|
|
|
extern void ppu_finalize(const ppu_module&);
|
2018-03-17 18:41:35 +01:00
|
|
|
|
extern void ppu_unload_prx(const lv2_prx&);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&, s64 = 0, utils::serial* = nullptr);
|
|
|
|
|
|
extern std::pair<std::shared_ptr<lv2_overlay>, CellError> ppu_load_overlay(const ppu_exec_object&, const std::string& path, s64 = 0, utils::serial* = nullptr);
|
2022-04-27 18:46:09 +02:00
|
|
|
|
extern bool ppu_load_rel_exec(const ppu_rel_object&);
|
2022-07-15 19:32:09 +02:00
|
|
|
|
extern bool is_savestate_version_compatible(const std::vector<std::pair<u16, u16>>& data, bool is_boot_check);
|
2022-07-11 16:08:34 +02:00
|
|
|
|
extern std::vector<std::pair<u16, u16>> read_used_savestate_versions();
|
2016-07-09 00:36:42 +02:00
|
|
|
|
|
2016-04-27 00:27:24 +02:00
|
|
|
|
fs::file g_tty;
|
2018-03-01 11:48:42 +01:00
|
|
|
|
atomic_t<s64> g_tty_size{0};
|
2018-06-29 07:59:56 +02:00
|
|
|
|
std::array<std::deque<std::string>, 16> g_tty_input;
|
|
|
|
|
|
std::mutex g_tty_mutex;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
thread_local std::string_view g_tls_serialize_name;
|
|
|
|
|
|
|
|
|
|
|
|
extern thread_local std::string(*g_tls_log_prefix)();
|
2016-04-27 00:27:24 +02:00
|
|
|
|
|
2020-12-09 16:04:52 +01:00
|
|
|
|
// Report error and call std::abort(), defined in main.cpp
|
2021-03-01 12:58:13 +01:00
|
|
|
|
[[noreturn]] void report_fatal_error(std::string_view);
|
2020-12-09 16:04:52 +01:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
void initialize_timebased_time(u64 timebased_init, bool reset = false);
|
|
|
|
|
|
|
2020-11-12 03:52:22 +01:00
|
|
|
|
namespace atomic_wait
|
|
|
|
|
|
{
|
2022-06-04 12:28:06 +02:00
|
|
|
|
extern void parse_hashtable(bool(*cb)(u64 id, u32 refs, u64 ptr, u32 max_coll));
|
2020-11-12 03:52:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-25 16:33:06 +01:00
|
|
|
|
template<>
|
|
|
|
|
|
void fmt_class_string<game_boot_result>::format(std::string& out, u64 arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
format_enum(out, arg, [](game_boot_result value)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
case game_boot_result::no_errors: return "No errors";
|
|
|
|
|
|
case game_boot_result::generic_error: return "Generic error";
|
|
|
|
|
|
case game_boot_result::nothing_to_boot: return "Nothing to boot";
|
|
|
|
|
|
case game_boot_result::wrong_disc_location: return "Wrong disc location";
|
|
|
|
|
|
case game_boot_result::invalid_file_or_folder: return "Invalid file or folder";
|
2022-07-07 22:00:59 +02:00
|
|
|
|
case game_boot_result::invalid_bdvd_folder: return "Invalid dev_bdvd folder";
|
2020-02-25 16:33:06 +01:00
|
|
|
|
case game_boot_result::install_failed: return "Game install failed";
|
|
|
|
|
|
case game_boot_result::decryption_error: return "Failed to decrypt content";
|
|
|
|
|
|
case game_boot_result::file_creation_error: return "Could not create important files";
|
2020-02-29 09:05:27 +01:00
|
|
|
|
case game_boot_result::firmware_missing: return "Firmware is missing";
|
2020-11-19 21:55:06 +01:00
|
|
|
|
case game_boot_result::unsupported_disc_type: return "This disc type is not supported yet";
|
2022-07-04 15:02:17 +02:00
|
|
|
|
case game_boot_result::savestate_corrupted: return "Savestate data is corrupted or it's not an RPCS3 savestate";
|
|
|
|
|
|
case game_boot_result::savestate_version_unsupported: return "Savestate versioning data differes from your RPCS3 build";
|
2020-02-25 16:33:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
return unknown;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
template<>
|
|
|
|
|
|
void fmt_class_string<cfg_mode>::format(std::string& out, u64 arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
format_enum(out, arg, [](cfg_mode value)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (value)
|
|
|
|
|
|
{
|
|
|
|
|
|
case cfg_mode::custom: return "custom config";
|
|
|
|
|
|
case cfg_mode::custom_selection: return "custom config selection";
|
|
|
|
|
|
case cfg_mode::global: return "global config";
|
|
|
|
|
|
case cfg_mode::config_override: return "config override";
|
|
|
|
|
|
case cfg_mode::continuous: return "continuous config";
|
|
|
|
|
|
case cfg_mode::default_config: return "default config";
|
|
|
|
|
|
}
|
|
|
|
|
|
return unknown;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-24 19:58:26 +02:00
|
|
|
|
void Emulator::CallFromMainThread(std::function<void()>&& func, atomic_t<bool>* wake_up, bool track_emu_state, u64 stop_ctr) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!track_emu_state)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_cb.call_from_main_thread(std::move(func), wake_up);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::function<void()> final_func = [this, before = IsStopped(), count = (stop_ctr == umax ? +m_stop_ctr : stop_ctr), func = std::move(func)]
|
|
|
|
|
|
{
|
|
|
|
|
|
if (count == m_stop_ctr && before == IsStopped())
|
|
|
|
|
|
{
|
|
|
|
|
|
func();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
m_cb.call_from_main_thread(std::move(final_func), wake_up);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Emulator::BlockingCallFromMainThread(std::function<void()>&& func) const
|
|
|
|
|
|
{
|
|
|
|
|
|
atomic_t<bool> wake_up = false;
|
|
|
|
|
|
|
|
|
|
|
|
CallFromMainThread(std::move(func), &wake_up);
|
|
|
|
|
|
|
|
|
|
|
|
while (!wake_up && !IsStopped())
|
|
|
|
|
|
{
|
2022-08-23 12:05:55 +02:00
|
|
|
|
ensure(thread_ctrl::get_current());
|
2022-06-24 19:58:26 +02:00
|
|
|
|
thread_ctrl::wait_on(wake_up, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
// This function ensures constant initialization order between different compilers and builds
|
|
|
|
|
|
void init_fxo_for_exec(utils::serial* ar, bool full = false)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_fxo->init<ppu_module>();
|
|
|
|
|
|
|
|
|
|
|
|
void init_ppu_functions(utils::serial* ar, bool full);
|
|
|
|
|
|
|
|
|
|
|
|
if (full)
|
|
|
|
|
|
{
|
|
|
|
|
|
init_ppu_functions(ar, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Emu.ConfigurePPUCache();
|
|
|
|
|
|
|
|
|
|
|
|
g_fxo->init(false, ar);
|
|
|
|
|
|
|
|
|
|
|
|
Emu.GetCallbacks().init_gs_render(ar);
|
|
|
|
|
|
Emu.GetCallbacks().init_pad_handler(Emu.GetTitleID());
|
|
|
|
|
|
Emu.GetCallbacks().init_kb_handler();
|
|
|
|
|
|
Emu.GetCallbacks().init_mouse_handler();
|
2022-07-09 12:19:08 +02:00
|
|
|
|
|
|
|
|
|
|
if (ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
Emu.ExecDeserializationRemnants();
|
|
|
|
|
|
ar->pos += 32; // Reserved area
|
|
|
|
|
|
}
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-01 23:34:48 +01:00
|
|
|
|
void Emulator::Init(bool add_only)
|
2012-11-15 00:39:56 +01:00
|
|
|
|
{
|
2019-01-26 21:15:45 +01:00
|
|
|
|
jit_runtime::initialize();
|
|
|
|
|
|
|
2016-04-27 00:27:24 +02:00
|
|
|
|
if (!g_tty)
|
|
|
|
|
|
{
|
2019-09-23 19:37:58 +02:00
|
|
|
|
const auto tty_path = fs::get_cache_dir() + "TTY.log";
|
|
|
|
|
|
g_tty.open(tty_path, fs::rewrite + fs::append);
|
|
|
|
|
|
|
|
|
|
|
|
if (!g_tty)
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.fatal("Failed to create TTY log: %s (%s)", tty_path, fs::g_tls_error);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
}
|
2016-04-27 00:27:24 +02:00
|
|
|
|
}
|
2017-10-31 22:23:09 +01:00
|
|
|
|
|
2019-08-20 03:49:22 +02:00
|
|
|
|
g_fxo->reset();
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
|
|
|
|
|
// Reset defaults, cache them
|
2021-09-23 20:12:06 +02:00
|
|
|
|
g_cfg_vfs.from_default();
|
2017-05-20 13:45:02 +02:00
|
|
|
|
g_cfg.from_default();
|
2021-09-22 21:44:52 +02:00
|
|
|
|
g_cfg.name.clear();
|
2020-09-29 18:26:54 +02:00
|
|
|
|
|
|
|
|
|
|
// Not all renderers are known at compile time, so set a provided default if possible
|
|
|
|
|
|
if (m_default_renderer == video_renderer::vulkan && !m_default_graphics_adapter.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.video.renderer.set(m_default_renderer);
|
|
|
|
|
|
g_cfg.video.vk.adapter.from_string(m_default_graphics_adapter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-05-20 13:45:02 +02:00
|
|
|
|
g_cfg_defaults = g_cfg.to_string();
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
2021-09-23 20:12:06 +02:00
|
|
|
|
// Load VFS config
|
|
|
|
|
|
g_cfg_vfs.load();
|
2021-10-20 19:51:47 +02:00
|
|
|
|
sys_log.notice("Using VFS config:\n%s", g_cfg_vfs.to_string());
|
|
|
|
|
|
|
|
|
|
|
|
// Mount all devices
|
|
|
|
|
|
const std::string emu_dir = rpcs3::utils::get_emu_dir();
|
|
|
|
|
|
const std::string elf_dir = fs::get_parent_dir(m_path);
|
2022-07-07 22:00:59 +02:00
|
|
|
|
const std::string dev_bdvd = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, emu_dir); // Only used for make_path
|
2022-05-08 00:13:21 +02:00
|
|
|
|
const std::string dev_hdd0 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd0, emu_dir);
|
|
|
|
|
|
const std::string dev_hdd1 = g_cfg_vfs.get(g_cfg_vfs.dev_hdd1, emu_dir);
|
|
|
|
|
|
const std::string dev_flsh = g_cfg_vfs.get_dev_flash();
|
|
|
|
|
|
const std::string dev_flsh2 = g_cfg_vfs.get_dev_flash2();
|
|
|
|
|
|
const std::string dev_flsh3 = g_cfg_vfs.get_dev_flash3();
|
2021-10-20 19:51:47 +02:00
|
|
|
|
|
2022-05-08 00:13:21 +02:00
|
|
|
|
vfs::mount("/dev_hdd0", dev_hdd0);
|
|
|
|
|
|
vfs::mount("/dev_flash", dev_flsh);
|
|
|
|
|
|
vfs::mount("/dev_flash2", dev_flsh2);
|
|
|
|
|
|
vfs::mount("/dev_flash3", dev_flsh3);
|
2021-10-20 19:51:47 +02:00
|
|
|
|
vfs::mount("/app_home", g_cfg_vfs.app_home.to_string().empty() ? elf_dir + '/' : g_cfg_vfs.get(g_cfg_vfs.app_home, emu_dir));
|
|
|
|
|
|
|
2022-05-08 00:13:21 +02:00
|
|
|
|
std::string dev_usb;
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& [key, value] : g_cfg_vfs.dev_usb.get_map())
|
|
|
|
|
|
{
|
|
|
|
|
|
const cfg::device_info usb_info = g_cfg_vfs.get_device(g_cfg_vfs.dev_usb, key, emu_dir);
|
|
|
|
|
|
|
|
|
|
|
|
if (key.size() != 11 || !key.starts_with("/dev_usb00"sv) || key.back() < '0' || key.back() > '7')
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Trying to mount unsupported usb device: %s", key);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vfs::mount(key, usb_info.path);
|
|
|
|
|
|
|
|
|
|
|
|
if (key == "/dev_usb000"sv)
|
|
|
|
|
|
{
|
|
|
|
|
|
dev_usb = usb_info.path;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ensure(!dev_usb.empty());
|
|
|
|
|
|
|
2021-10-20 19:51:47 +02:00
|
|
|
|
if (!hdd1.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
vfs::mount("/dev_hdd1", hdd1);
|
|
|
|
|
|
sys_log.notice("Hdd1: %s", vfs::get("/dev_hdd1"));
|
|
|
|
|
|
}
|
2021-09-23 20:12:06 +02:00
|
|
|
|
|
2022-01-07 18:09:35 +01:00
|
|
|
|
const bool is_exitspawn = m_config_mode == cfg_mode::continuous;
|
|
|
|
|
|
|
2021-09-08 14:23:50 +02:00
|
|
|
|
// Load config file
|
2021-09-22 21:44:52 +02:00
|
|
|
|
if (m_config_mode == cfg_mode::config_override)
|
2019-09-23 19:37:58 +02:00
|
|
|
|
{
|
2021-09-08 14:23:50 +02:00
|
|
|
|
if (const fs::file cfg_file{m_config_path, fs::read + fs::create})
|
2020-08-03 15:17:44 +02:00
|
|
|
|
{
|
2021-09-13 01:21:11 +02:00
|
|
|
|
sys_log.notice("Applying config override: %s", m_config_path);
|
|
|
|
|
|
|
2020-08-03 15:17:44 +02:00
|
|
|
|
if (!g_cfg.from_string(cfg_file.to_string()))
|
|
|
|
|
|
{
|
2021-09-08 14:23:50 +02:00
|
|
|
|
sys_log.fatal("Failed to apply config: %s. Proceeding with regular configuration.", m_config_path);
|
2021-09-22 21:44:52 +02:00
|
|
|
|
m_config_path.clear();
|
|
|
|
|
|
m_config_mode = cfg_mode::custom;
|
2020-08-03 15:17:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-09-08 14:23:50 +02:00
|
|
|
|
sys_log.success("Applied config override: %s", m_config_path);
|
|
|
|
|
|
g_cfg.name = m_config_path;
|
2020-08-03 15:17:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2020-07-28 19:01:07 +02:00
|
|
|
|
{
|
2021-09-08 14:23:50 +02:00
|
|
|
|
sys_log.fatal("Failed to access config: %s (%s). Proceeding with regular configuration.", m_config_path, fs::g_tls_error);
|
2021-09-22 21:44:52 +02:00
|
|
|
|
m_config_path.clear();
|
|
|
|
|
|
m_config_mode = cfg_mode::custom;
|
2020-07-28 19:01:07 +02:00
|
|
|
|
}
|
2019-09-23 19:37:58 +02:00
|
|
|
|
}
|
2020-08-03 15:17:44 +02:00
|
|
|
|
|
|
|
|
|
|
// Reload global configuration
|
2021-09-22 21:44:52 +02:00
|
|
|
|
if (m_config_mode != cfg_mode::config_override && m_config_mode != cfg_mode::default_config)
|
2019-09-23 19:37:58 +02:00
|
|
|
|
{
|
2020-08-03 15:17:44 +02:00
|
|
|
|
const auto cfg_path = fs::get_config_dir() + "/config.yml";
|
|
|
|
|
|
|
|
|
|
|
|
if (const fs::file cfg_file{cfg_path, fs::read + fs::create})
|
|
|
|
|
|
{
|
2021-09-13 01:21:11 +02:00
|
|
|
|
sys_log.notice("Applying global config: %s", cfg_path);
|
|
|
|
|
|
|
2020-08-03 15:17:44 +02:00
|
|
|
|
if (!g_cfg.from_string(cfg_file.to_string()))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Failed to apply global config: %s", cfg_path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g_cfg.name = cfg_path;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Failed to access global config: %s (%s)", cfg_path, fs::g_tls_error);
|
|
|
|
|
|
}
|
2019-09-23 19:37:58 +02:00
|
|
|
|
}
|
2017-02-11 19:06:57 +01:00
|
|
|
|
|
2018-11-01 11:21:57 +01:00
|
|
|
|
// Create directories (can be disabled if necessary)
|
2019-09-23 19:37:58 +02:00
|
|
|
|
auto make_path_verbose = [](const std::string& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fs::create_path(path))
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.fatal("Failed to create path: %s (%s)", path, fs::g_tls_error);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2019-09-25 00:49:13 +02:00
|
|
|
|
const std::string save_path = dev_hdd0 + "home/" + m_usr + "/savedata/";
|
2020-08-06 19:04:47 +02:00
|
|
|
|
const std::string user_path = dev_hdd0 + "home/" + m_usr + "/localusername";
|
2019-09-25 00:49:13 +02:00
|
|
|
|
|
2018-11-01 11:21:57 +01:00
|
|
|
|
if (g_cfg.vfs.init_dirs)
|
|
|
|
|
|
{
|
2022-07-07 22:00:59 +02:00
|
|
|
|
make_path_verbose(dev_bdvd);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
make_path_verbose(dev_hdd0);
|
|
|
|
|
|
make_path_verbose(dev_hdd1);
|
2020-02-20 10:43:53 +01:00
|
|
|
|
make_path_verbose(dev_flsh);
|
2021-04-17 16:22:17 +02:00
|
|
|
|
make_path_verbose(dev_flsh2);
|
|
|
|
|
|
make_path_verbose(dev_flsh3);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
make_path_verbose(dev_usb);
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "game/");
|
2021-08-19 07:49:59 +02:00
|
|
|
|
make_path_verbose(dev_hdd0 + reinterpret_cast<const char*>(u8"game/$locks/"));
|
2019-09-23 19:37:58 +02:00
|
|
|
|
make_path_verbose(dev_hdd0 + "home/");
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "home/" + m_usr + "/");
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "home/" + m_usr + "/exdata/");
|
2019-09-25 00:49:13 +02:00
|
|
|
|
make_path_verbose(save_path);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
make_path_verbose(dev_hdd0 + "home/" + m_usr + "/trophy/");
|
|
|
|
|
|
|
2020-08-06 19:04:47 +02:00
|
|
|
|
if (!fs::write_file(user_path, fs::create + fs::excl + fs::write, "User"s))
|
2019-09-23 19:37:58 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (fs::g_tls_error != fs::error::exist)
|
|
|
|
|
|
{
|
2020-08-06 19:04:47 +02:00
|
|
|
|
sys_log.fatal("Failed to create file: %s (%s)", user_path, fs::g_tls_error);
|
2019-09-23 19:37:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "disc/");
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "savedata/");
|
|
|
|
|
|
make_path_verbose(dev_hdd0 + "savedata/vmc/");
|
2021-02-28 20:05:04 +01:00
|
|
|
|
make_path_verbose(dev_hdd0 + "photo/");
|
2019-11-05 16:09:03 +01:00
|
|
|
|
make_path_verbose(dev_hdd1 + "caches/");
|
2018-11-01 11:21:57 +01:00
|
|
|
|
}
|
2018-06-22 13:12:21 +02:00
|
|
|
|
|
2021-02-01 23:34:48 +01:00
|
|
|
|
make_path_verbose(fs::get_cache_dir() + "shaderlog/");
|
|
|
|
|
|
make_path_verbose(fs::get_cache_dir() + "spu_progs/");
|
2022-07-04 15:02:17 +02:00
|
|
|
|
make_path_verbose(fs::get_cache_dir() + "/savestates/");
|
2021-02-01 23:34:48 +01:00
|
|
|
|
make_path_verbose(fs::get_config_dir() + "captures/");
|
2021-10-31 00:48:41 +02:00
|
|
|
|
make_path_verbose(fs::get_config_dir() + "sounds/");
|
2021-09-08 00:09:53 +02:00
|
|
|
|
make_path_verbose(patch_engine::get_patches_path());
|
2021-02-01 23:34:48 +01:00
|
|
|
|
|
|
|
|
|
|
if (add_only)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We don't need to initialize the rest if we only add games
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-06 19:04:47 +02:00
|
|
|
|
// Log user
|
|
|
|
|
|
if (m_usr.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("No user configured");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string username;
|
|
|
|
|
|
|
|
|
|
|
|
if (const fs::file file = fs::file(user_path))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (const std::string localusername = file.to_string(); !localusername.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
username = localusername;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.warning("Empty username in file: '%s'. Consider setting a username for user '%s' in the user manager.", user_path, m_usr);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Could not read file: '%s'", user_path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (username.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("Logged in as user '%s'", m_usr);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("Logged in as user '%s' with the username '%s'", m_usr, username);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-01-07 21:00:55 +01:00
|
|
|
|
if (is_exitspawn)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Actions not taken during exitspawn
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-09-25 00:49:13 +02:00
|
|
|
|
// Fixup savedata
|
|
|
|
|
|
for (const auto& entry : fs::dir(save_path))
|
|
|
|
|
|
{
|
2020-02-17 22:43:23 +01:00
|
|
|
|
if (entry.is_directory && entry.name.starts_with(".backup_"))
|
2019-09-25 00:49:13 +02:00
|
|
|
|
{
|
|
|
|
|
|
const std::string desired = entry.name.substr(8);
|
|
|
|
|
|
const std::string pending = save_path + ".working_" + desired;
|
|
|
|
|
|
|
|
|
|
|
|
if (fs::is_dir(pending))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Finalize interrupted saving
|
|
|
|
|
|
if (!fs::rename(pending, save_path + desired, false))
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.fatal("Failed to fix save data: %s (%s)", pending, fs::g_tls_error);
|
2019-09-25 00:49:13 +02:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
2021-04-12 22:23:24 +02:00
|
|
|
|
|
|
|
|
|
|
sys_log.success("Fixed save data: %s", desired);
|
2019-09-25 00:49:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Remove pending backup data
|
|
|
|
|
|
if (!fs::remove_all(save_path + entry.name))
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.fatal("Failed to remove save data backup: %s%s (%s)", save_path, entry.name, fs::g_tls_error);
|
2019-09-25 00:49:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.success("Removed save data backup: %s%s", save_path, entry.name);
|
2019-09-25 00:49:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-01 23:34:48 +01:00
|
|
|
|
// Limit cache size
|
2022-01-07 21:00:55 +01:00
|
|
|
|
if (g_cfg.vfs.limit_cache_size)
|
2022-01-07 18:16:03 +01:00
|
|
|
|
{
|
2021-04-21 22:12:21 +02:00
|
|
|
|
rpcs3::cache::limit_cache_size();
|
2022-01-07 18:16:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Wipe clean VSH's temporary directory of choice
|
2022-01-07 21:00:55 +01:00
|
|
|
|
if (g_cfg.vfs.empty_hdd0_tmp && !fs::remove_all(dev_hdd0 + "tmp/", false, true))
|
2022-01-07 18:16:03 +01:00
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Could not clean /dev_hdd0/tmp/ (%s)", fs::g_tls_error);
|
|
|
|
|
|
}
|
2022-01-07 21:00:55 +01:00
|
|
|
|
|
|
|
|
|
|
// Remove temporary game data that would have been removed when cellGame has been properly shut
|
|
|
|
|
|
for (const auto& entry : fs::dir(dev_hdd0 + "game/"))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (entry.name.starts_with("_GDATA_") && fs::is_dir(dev_hdd0 + "game/" + entry.name + "/USRDIR/"))
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string target = dev_hdd0 + "game/" + entry.name;
|
|
|
|
|
|
|
|
|
|
|
|
if (!fs::remove_all(target, true, true))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Could not clean \"%s\" (%s)", target, fs::g_tls_error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-06-18 21:30:38 +02:00
|
|
|
|
|
|
|
|
|
|
// Load IPC config
|
|
|
|
|
|
g_cfg_ipc.load();
|
|
|
|
|
|
sys_log.notice("Using IPC config:\n%s", g_cfg_ipc.to_string());
|
|
|
|
|
|
g_fxo->get<IPC_socket::IPC_server_manager>().set_server_enabled(g_cfg_ipc.get_server_enabled());
|
2020-02-28 19:52:09 +01:00
|
|
|
|
}
|
2018-05-30 19:34:36 +02:00
|
|
|
|
|
2021-04-02 00:54:32 +02:00
|
|
|
|
void Emulator::SetUsr(const std::string& user)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("Setting user ID '%s'", user);
|
|
|
|
|
|
|
2021-04-21 22:12:21 +02:00
|
|
|
|
const u32 id = rpcs3::utils::check_user(user);
|
2018-07-23 23:55:27 +02:00
|
|
|
|
|
|
|
|
|
|
if (id == 0)
|
|
|
|
|
|
{
|
2021-04-02 00:54:32 +02:00
|
|
|
|
fmt::throw_exception("Failed to set user ID '%s'", user);
|
2018-07-23 23:55:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_usrid = id;
|
|
|
|
|
|
m_usr = user;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-07 16:49:42 +01:00
|
|
|
|
std::string Emulator::GetBackgroundPicturePath() const
|
2019-07-19 21:36:23 +02:00
|
|
|
|
{
|
2020-10-07 14:20:35 +02:00
|
|
|
|
// Try to find a custom icon first
|
2021-04-07 23:05:18 +02:00
|
|
|
|
std::string path = fs::get_config_dir() + "/Icons/game_icons/" + GetTitleID() + "/PIC1.PNG";
|
2019-07-19 21:36:23 +02:00
|
|
|
|
|
2020-10-07 14:20:35 +02:00
|
|
|
|
if (fs::is_file(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
return path;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
path = m_sfo_dir + "/PIC1.PNG";
|
|
|
|
|
|
|
|
|
|
|
|
if (!fs::is_file(path))
|
2019-07-19 21:36:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
const std::string disc_dir = vfs::get("/dev_bdvd/PS3_GAME");
|
|
|
|
|
|
|
|
|
|
|
|
if (disc_dir.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Fallback to ICON0.PNG
|
|
|
|
|
|
path = m_sfo_dir + "/ICON0.PNG";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Fallback to PIC1.PNG in disc dir
|
|
|
|
|
|
path = disc_dir + "/PIC1.PNG";
|
|
|
|
|
|
|
2020-10-07 14:20:35 +02:00
|
|
|
|
if (!fs::is_file(path))
|
2019-07-19 21:36:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
// Fallback to ICON0.PNG in update dir
|
|
|
|
|
|
path = m_sfo_dir + "/ICON0.PNG";
|
|
|
|
|
|
|
2020-10-07 14:20:35 +02:00
|
|
|
|
if (!fs::is_file(path))
|
2019-07-19 21:36:23 +02:00
|
|
|
|
{
|
|
|
|
|
|
// Fallback to ICON0.PNG in disc dir
|
|
|
|
|
|
path = disc_dir + "/ICON0.PNG";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-05-13 11:18:05 +02:00
|
|
|
|
bool Emulator::BootRsxCapture(const std::string& path)
|
|
|
|
|
|
{
|
2021-01-28 08:29:13 +01:00
|
|
|
|
fs::file in_file(path);
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
2021-01-28 08:29:13 +01:00
|
|
|
|
if (!in_file)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<rsx::frame_capture_data> frame = std::make_unique<rsx::frame_capture_data>();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
utils::serial load;
|
|
|
|
|
|
load.set_reading_state();
|
|
|
|
|
|
in_file.read(load.data, in_file.size());
|
|
|
|
|
|
load.data.shrink_to_fit();
|
2021-06-01 18:13:05 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
load(*frame);
|
2021-01-28 08:29:13 +01:00
|
|
|
|
in_file.close();
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
2021-06-01 18:13:05 +02:00
|
|
|
|
if (frame->magic != rsx::c_fc_magic)
|
2018-05-13 11:18:05 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Invalid rsx capture file!");
|
2018-05-13 11:18:05 +02:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-01 18:13:05 +02:00
|
|
|
|
if (frame->version != rsx::c_fc_version)
|
2018-05-13 11:18:05 +02:00
|
|
|
|
{
|
2021-06-01 18:13:05 +02:00
|
|
|
|
sys_log.error("Rsx capture file version not supported! Expected %d, found %d", +rsx::c_fc_version, frame->version);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-02 19:00:30 +02:00
|
|
|
|
if (frame->LE_format != u32{std::endian::little == std::endian::native})
|
2021-06-01 18:13:05 +02:00
|
|
|
|
{
|
|
|
|
|
|
static constexpr std::string_view machines[2]{"Big-Endian", "Little-Endian"};
|
|
|
|
|
|
|
|
|
|
|
|
sys_log.error("Rsx capture byte endianness not supported! Expected %s format, found %s format"
|
|
|
|
|
|
, machines[frame->LE_format ^ 1], machines[frame->LE_format]);
|
|
|
|
|
|
|
2018-05-13 11:18:05 +02:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Init();
|
2019-01-13 18:06:30 +01:00
|
|
|
|
g_cfg.video.disable_on_disk_shader_cache.set(true);
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
|
|
|
|
|
vm::init();
|
2021-02-03 19:14:31 +01:00
|
|
|
|
g_fxo->init(false);
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
2021-09-08 00:09:53 +02:00
|
|
|
|
// Initialize progress dialog
|
|
|
|
|
|
g_fxo->init<named_thread<progress_dialog_server>>();
|
|
|
|
|
|
|
2022-03-11 21:08:44 +01:00
|
|
|
|
// Initialize performance monitor
|
|
|
|
|
|
g_fxo->init<named_thread<perf_monitor>>();
|
|
|
|
|
|
|
2018-05-13 11:18:05 +02:00
|
|
|
|
// PS3 'executable'
|
|
|
|
|
|
m_state = system_state::ready;
|
|
|
|
|
|
GetCallbacks().on_ready();
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
GetCallbacks().init_gs_render(nullptr);
|
2021-04-07 23:05:18 +02:00
|
|
|
|
GetCallbacks().init_pad_handler("");
|
2019-01-08 22:10:07 +01:00
|
|
|
|
|
2020-02-07 21:55:29 +01:00
|
|
|
|
GetCallbacks().on_run(false);
|
2022-07-12 15:04:33 +02:00
|
|
|
|
m_state = system_state::starting;
|
2018-05-13 11:18:05 +02:00
|
|
|
|
|
2022-07-12 15:04:33 +02:00
|
|
|
|
ensure(g_fxo->init<named_thread<rsx::rsx_replay_thread>>("RSX Replay", std::move(frame)));
|
2018-10-22 21:48:19 +02:00
|
|
|
|
|
2018-05-13 11:18:05 +02:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
game_boot_result Emulator::GetElfPathFromDir(std::string& elf_path, const std::string& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!fs::is_dir(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char* boot_list[] =
|
|
|
|
|
|
{
|
|
|
|
|
|
"/EBOOT.BIN",
|
|
|
|
|
|
"/USRDIR/EBOOT.BIN",
|
|
|
|
|
|
"/USRDIR/ISO.BIN.EDAT",
|
|
|
|
|
|
"/PS3_GAME/USRDIR/EBOOT.BIN",
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
for (std::string elf : boot_list)
|
|
|
|
|
|
{
|
|
|
|
|
|
elf = path + elf;
|
|
|
|
|
|
|
|
|
|
|
|
if (fs::is_file(elf))
|
|
|
|
|
|
{
|
|
|
|
|
|
elf_path = elf;
|
|
|
|
|
|
return game_boot_result::no_errors;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
game_boot_result Emulator::BootGame(const std::string& path, const std::string& title_id, bool direct, bool add_only, cfg_mode config_mode, const std::string& config_path)
|
2013-12-08 17:54:45 +01:00
|
|
|
|
{
|
2021-02-01 21:47:11 +01:00
|
|
|
|
if (!fs::exists(path))
|
2013-12-08 17:54:45 +01:00
|
|
|
|
{
|
2021-02-01 21:47:11 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
2015-04-19 15:19:24 +02:00
|
|
|
|
|
2019-01-06 23:30:38 +01:00
|
|
|
|
m_path_old = m_path;
|
|
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
m_config_mode = config_mode;
|
2021-09-08 14:23:50 +02:00
|
|
|
|
m_config_path = config_path;
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (fs::file save{path, fs::isfile + fs::read}; save && save.size() >= 8 && save.read<u64>() == "RPCS3SAV"_u64)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_ar = std::make_shared<utils::serial>();
|
|
|
|
|
|
m_ar->set_reading_state();
|
|
|
|
|
|
save.seek(0);
|
|
|
|
|
|
save.read(m_ar->data, save.size());
|
|
|
|
|
|
m_ar->data.shrink_to_fit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (direct || m_ar || fs::is_file(path))
|
2014-12-14 18:14:26 +01:00
|
|
|
|
{
|
2017-09-18 18:16:36 +02:00
|
|
|
|
m_path = path;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
|
|
|
|
|
auto error = Load(title_id, add_only);
|
|
|
|
|
|
|
|
|
|
|
|
if (g_cfg.savestate.suspend_emu && m_ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
fs::remove_file(path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return error;
|
2014-12-14 18:14:26 +01:00
|
|
|
|
}
|
2013-12-08 17:54:45 +01:00
|
|
|
|
|
2020-02-25 16:33:06 +01:00
|
|
|
|
game_boot_result result = game_boot_result::nothing_to_boot;
|
2021-02-01 21:47:11 +01:00
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
std::string elf;
|
|
|
|
|
|
if (const game_boot_result res = GetElfPathFromDir(elf, path); res == game_boot_result::no_errors)
|
2021-02-01 21:47:11 +01:00
|
|
|
|
{
|
2022-06-21 22:13:22 +02:00
|
|
|
|
ensure(!elf.empty());
|
|
|
|
|
|
m_path = elf;
|
|
|
|
|
|
result = Load(title_id, add_only);
|
2013-12-08 17:54:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-06-01 00:12:30 +02:00
|
|
|
|
if (add_only)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (auto&& entry : fs::dir{ path })
|
|
|
|
|
|
{
|
|
|
|
|
|
if (entry.name == "." || entry.name == "..")
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (entry.is_directory && std::regex_match(entry.name, std::regex("^PS3_GM[[:digit:]]{2}$")))
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string elf = path + "/" + entry.name + "/USRDIR/EBOOT.BIN";
|
|
|
|
|
|
|
|
|
|
|
|
if (fs::is_file(elf))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_path = elf;
|
2021-09-08 14:23:50 +02:00
|
|
|
|
if (const auto err = Load(title_id, add_only); err != game_boot_result::no_errors)
|
2020-02-25 16:33:06 +01:00
|
|
|
|
{
|
|
|
|
|
|
result = err;
|
|
|
|
|
|
}
|
2019-06-01 00:12:30 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return result;
|
2013-12-08 17:54:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-01 12:55:46 +01:00
|
|
|
|
void Emulator::SetForceBoot(bool force_boot)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_force_boot = force_boot;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-08 14:23:50 +02:00
|
|
|
|
game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool is_disc_patch)
|
2012-11-15 00:39:56 +01:00
|
|
|
|
{
|
2022-04-09 23:28:52 +02:00
|
|
|
|
if (m_config_mode == cfg_mode::continuous)
|
|
|
|
|
|
{
|
|
|
|
|
|
// The program is being booted from another running program
|
|
|
|
|
|
// CELL_GAME_GAMETYPE_GAMEDATA is not used as boot type
|
|
|
|
|
|
|
|
|
|
|
|
if (m_cat == "DG"sv)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_boot_source_type = CELL_GAME_GAMETYPE_DISC;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (m_cat == "HM"sv)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_boot_source_type = CELL_GAME_GAMETYPE_HOME;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_boot_source_type = CELL_GAME_GAMETYPE_HDD;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
m_boot_source_type = CELL_GAME_GAMETYPE_SYS;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-11-01 12:55:46 +01:00
|
|
|
|
if (!IsStopped())
|
|
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
Kill();
|
2017-11-01 12:55:46 +01:00
|
|
|
|
}
|
2015-07-01 00:25:52 +02:00
|
|
|
|
|
2019-06-01 00:12:30 +02:00
|
|
|
|
if (!title_id.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
m_title_id = title_id;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
sys_log.notice("Selected config: mode=%s, path=\"%s\"", m_config_mode, m_config_path);
|
2021-10-20 19:51:47 +02:00
|
|
|
|
sys_log.notice("Path: %s", m_path);
|
2021-09-13 01:21:11 +02:00
|
|
|
|
|
2022-07-19 05:54:06 +02:00
|
|
|
|
struct cleanup_t
|
|
|
|
|
|
{
|
|
|
|
|
|
Emulator* _this;
|
|
|
|
|
|
bool cleanup = true;
|
|
|
|
|
|
|
|
|
|
|
|
~cleanup_t()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cleanup && _this->IsStopped())
|
|
|
|
|
|
{
|
|
|
|
|
|
_this->Kill(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} cleanup{this};
|
|
|
|
|
|
|
2015-07-04 21:23:10 +02:00
|
|
|
|
{
|
2021-02-01 23:34:48 +01:00
|
|
|
|
Init(add_only);
|
2013-12-08 17:54:45 +01:00
|
|
|
|
|
2017-09-13 01:49:02 +02:00
|
|
|
|
// Load game list (maps ABCD12345 IDs to /dev_bdvd/ locations)
|
2020-03-09 17:18:39 +01:00
|
|
|
|
YAML::Node games;
|
|
|
|
|
|
|
|
|
|
|
|
if (fs::file f{fs::get_config_dir() + "/games.yml", fs::read + fs::create})
|
|
|
|
|
|
{
|
|
|
|
|
|
auto [result, error] = yaml_load(f.to_string());
|
|
|
|
|
|
|
|
|
|
|
|
if (!error.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to load games.yml: %s", error);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
games = result;
|
|
|
|
|
|
}
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
|
|
|
|
|
if (!games.IsMap())
|
|
|
|
|
|
{
|
|
|
|
|
|
games.reset();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
m_state_inspection_savestate = g_cfg.savestate.state_inspection_mode.get();
|
|
|
|
|
|
|
|
|
|
|
|
if (m_ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
struct file_header
|
|
|
|
|
|
{
|
|
|
|
|
|
ENABLE_BITWISE_SERIALIZATION;
|
|
|
|
|
|
|
|
|
|
|
|
nse_t<u64, 1> magic;
|
|
|
|
|
|
bool LE_format;
|
|
|
|
|
|
bool state_inspection_support;
|
|
|
|
|
|
nse_t<u64, 1> offset;
|
2022-07-09 12:19:08 +02:00
|
|
|
|
std::array<u8, 32> reserved;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
};
|
2022-08-05 03:28:23 +02:00
|
|
|
|
|
2022-07-05 13:12:21 +02:00
|
|
|
|
const auto header = m_ar->try_read<file_header>().second;
|
2022-08-05 03:28:23 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (header.magic != "RPCS3SAV"_u64)
|
|
|
|
|
|
{
|
|
|
|
|
|
return game_boot_result::savestate_corrupted;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-11 16:08:34 +02:00
|
|
|
|
if (header.LE_format != (std::endian::native == std::endian::little) || header.offset >= m_ar->data.size())
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
|
|
|
|
|
return game_boot_result::savestate_corrupted;
|
|
|
|
|
|
}
|
2022-08-05 03:28:23 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
g_cfg.savestate.state_inspection_mode.set(header.state_inspection_support);
|
|
|
|
|
|
|
|
|
|
|
|
// Emulate seek operation (please avoid using in other places)
|
|
|
|
|
|
m_ar->pos = header.offset;
|
2022-07-11 16:08:34 +02:00
|
|
|
|
|
|
|
|
|
|
if (!is_savestate_version_compatible(m_ar->operator std::vector<std::pair<u16, u16>>(), true))
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
|
|
|
|
|
return game_boot_result::savestate_version_unsupported;
|
|
|
|
|
|
}
|
2022-07-11 16:08:34 +02:00
|
|
|
|
|
|
|
|
|
|
m_ar->pos = sizeof(file_header); // Restore position
|
2022-08-05 03:28:23 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
argv.clear();
|
|
|
|
|
|
klic.clear();
|
|
|
|
|
|
|
2022-08-05 03:28:23 +02:00
|
|
|
|
std::string disc_info;
|
|
|
|
|
|
(*m_ar)(argv.emplace_back(), disc_info, klic.emplace_back(), m_game_dir, hdd1);
|
2022-07-09 12:19:08 +02:00
|
|
|
|
|
|
|
|
|
|
if (!klic[0])
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
2022-07-09 12:19:08 +02:00
|
|
|
|
klic.clear();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
2022-08-05 03:28:23 +02:00
|
|
|
|
|
|
|
|
|
|
if (!disc_info.empty() && disc_info[0] != '/')
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
2022-08-05 03:28:23 +02:00
|
|
|
|
// Restore disc path for disc games (must exist in games.yml i.e. your game library)
|
|
|
|
|
|
m_title_id = disc_info;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
|
|
|
|
|
// Load /dev_bdvd/ from game list if available
|
|
|
|
|
|
if (auto node = games[m_title_id])
|
|
|
|
|
|
{
|
|
|
|
|
|
disc = node.Scalar();
|
|
|
|
|
|
}
|
2022-08-05 03:28:23 +02:00
|
|
|
|
else if (!g_cfg.savestate.state_inspection_mode)
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Disc directory not found. Savestate cannot be loaded. ('%s')", m_title_id);
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-07-09 12:19:08 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
auto load_tar = [&](const std::string& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
const usz size = *m_ar;
|
|
|
|
|
|
|
|
|
|
|
|
if (size)
|
|
|
|
|
|
{
|
|
|
|
|
|
fs::remove_all(path, false);
|
|
|
|
|
|
ensure(tar_object(fs::file(&m_ar->data[m_ar->pos], size)).extract(path));
|
|
|
|
|
|
m_ar->pos += size;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (!hdd1.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
hdd1 = rpcs3::utils::get_hdd1_dir() + "caches/" + hdd1 + "/";
|
|
|
|
|
|
load_tar(hdd1);
|
|
|
|
|
|
}
|
2022-07-09 12:19:08 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
for (const std::string hdd0_game = rpcs3::utils::get_hdd0_dir() + "game/";;)
|
|
|
|
|
|
{
|
2022-07-09 12:19:08 +02:00
|
|
|
|
const std::string game_data = *m_ar;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
|
|
|
|
|
if (game_data.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
load_tar(hdd0_game + game_data);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-09 12:19:08 +02:00
|
|
|
|
m_ar->pos += 32; // Reserved area
|
|
|
|
|
|
|
2022-08-05 03:28:23 +02:00
|
|
|
|
if (disc_info.starts_with("/"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Restore SFO directory for PSN games
|
|
|
|
|
|
|
|
|
|
|
|
if (disc_info.starts_with("/dev_hdd0"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
disc = rpcs3::utils::get_hdd0_dir();
|
|
|
|
|
|
disc += std::string_view(disc_info).substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (disc_info.starts_with("/host_root"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Host root has been used in savestates!");
|
|
|
|
|
|
disc = disc_info.substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Unknown source for game SFO directory: %s", disc_info);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_cat.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (argv[0].starts_with("/dev_hdd0"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_path = rpcs3::utils::get_hdd0_dir();
|
|
|
|
|
|
m_path += std::string_view(argv[0]).substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (argv[0].starts_with("/dev_flash"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_path = g_cfg_vfs.get_dev_flash();
|
|
|
|
|
|
m_path += std::string_view(argv[0]).substr(10);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (argv[0].starts_with("/dev_bdvd"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_path = disc;
|
|
|
|
|
|
m_path += std::string_view(argv[0]).substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (argv[0].starts_with("/host_root"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Host root has been used in savestates!");
|
|
|
|
|
|
m_path = argv[0].substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (argv[0].starts_with("/dev_hdd1"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("HDD1 has been used to store executable in savestates!");
|
|
|
|
|
|
m_path = rpcs3::utils::get_hdd1_dir();
|
|
|
|
|
|
m_path += std::string_view(argv[0]).substr(9);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Unknown source for savestates: %s", argv[0]);
|
|
|
|
|
|
}
|
2022-07-09 12:19:08 +02:00
|
|
|
|
|
|
|
|
|
|
sys_log.notice("Restored executable path: \'%s\'", m_path);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const std::string resolved_path = GetCallbacks().resolve_path(m_path);
|
|
|
|
|
|
|
2017-02-22 13:21:30 +01:00
|
|
|
|
const std::string elf_dir = fs::get_parent_dir(m_path);
|
|
|
|
|
|
|
2022-07-07 22:00:59 +02:00
|
|
|
|
// Mount /app_home again since m_path might have changed due to savestates.
|
2022-07-04 15:02:17 +02:00
|
|
|
|
vfs::mount("/app_home", g_cfg_vfs.app_home.to_string().empty() ? elf_dir + '/' : g_cfg_vfs.get(g_cfg_vfs.app_home, rpcs3::utils::get_emu_dir()));
|
|
|
|
|
|
|
2017-02-22 13:21:30 +01:00
|
|
|
|
// Load PARAM.SFO (TODO)
|
2018-12-03 23:46:01 +01:00
|
|
|
|
psf::registry _psf;
|
|
|
|
|
|
if (fs::file sfov{elf_dir + "/sce_sys/param.sfo"})
|
|
|
|
|
|
{
|
|
|
|
|
|
m_sfo_dir = elf_dir;
|
|
|
|
|
|
_psf = psf::load_object(sfov);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2017-07-12 18:35:46 +02:00
|
|
|
|
{
|
2018-03-17 18:41:35 +01:00
|
|
|
|
if (fs::is_dir(m_path))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Special case (directory scan)
|
2021-04-21 22:12:21 +02:00
|
|
|
|
m_sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(m_path, m_title_id);
|
2018-03-17 18:41:35 +01:00
|
|
|
|
}
|
2020-02-26 21:13:54 +01:00
|
|
|
|
else if (!disc.empty())
|
2017-07-12 18:35:46 +02:00
|
|
|
|
{
|
2017-12-25 21:14:57 +01:00
|
|
|
|
// Check previously used category before it's overwritten
|
|
|
|
|
|
if (m_cat == "DG")
|
|
|
|
|
|
{
|
2019-06-01 00:12:30 +02:00
|
|
|
|
m_sfo_dir = disc + "/" + m_game_dir;
|
2017-12-25 21:14:57 +01:00
|
|
|
|
}
|
2018-12-03 23:46:01 +01:00
|
|
|
|
else if (m_cat == "GD")
|
2017-12-25 21:14:57 +01:00
|
|
|
|
{
|
2021-04-21 22:12:21 +02:00
|
|
|
|
m_sfo_dir = rpcs3::utils::get_hdd0_dir() + "game/" + m_title_id;
|
2018-12-03 23:46:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-04-21 22:12:21 +02:00
|
|
|
|
m_sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(disc, m_title_id);
|
2017-12-25 21:14:57 +01:00
|
|
|
|
}
|
2017-07-12 18:35:46 +02:00
|
|
|
|
}
|
2018-12-03 23:46:01 +01:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-04-21 22:12:21 +02:00
|
|
|
|
m_sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(elf_dir + "/../", m_title_id);
|
2018-12-03 23:46:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_psf = psf::load_object(fs::file(m_sfo_dir + "/PARAM.SFO"));
|
|
|
|
|
|
}
|
2017-10-31 22:23:09 +01:00
|
|
|
|
|
2021-04-06 22:16:58 +02:00
|
|
|
|
m_title = std::string(psf::get_string(_psf, "TITLE", std::string_view(m_path).substr(m_path.find_last_of(fs::delim) + 1)));
|
2020-08-22 00:55:17 +02:00
|
|
|
|
m_title_id = std::string(psf::get_string(_psf, "TITLE_ID"));
|
|
|
|
|
|
m_cat = std::string(psf::get_string(_psf, "CATEGORY"));
|
2017-02-22 13:21:30 +01:00
|
|
|
|
|
2020-09-21 11:04:11 +02:00
|
|
|
|
const auto version_app = psf::get_string(_psf, "APP_VER", "Unknown");
|
2020-08-22 00:55:17 +02:00
|
|
|
|
const auto version_disc = psf::get_string(_psf, "VERSION", "Unknown");
|
2020-09-21 11:04:11 +02:00
|
|
|
|
m_app_version = version_app == "Unknown" ? version_disc : version_app;
|
2019-09-27 18:27:17 +02:00
|
|
|
|
|
2017-12-29 18:05:06 +01:00
|
|
|
|
if (!_psf.empty() && m_cat.empty())
|
|
|
|
|
|
{
|
2020-02-25 16:33:06 +01:00
|
|
|
|
sys_log.fatal("Corrupted PARAM.SFO found! Try reinstalling the game.");
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2017-12-29 18:05:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Title: %s", GetTitle());
|
|
|
|
|
|
sys_log.notice("Serial: %s", GetTitleID());
|
|
|
|
|
|
sys_log.notice("Category: %s", GetCat());
|
2020-09-21 11:04:11 +02:00
|
|
|
|
sys_log.notice("Version: APP_VER=%s VERSION=%s", version_app, version_disc);
|
2017-02-28 12:10:04 +01:00
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
if (!add_only)
|
2017-02-28 12:10:04 +01:00
|
|
|
|
{
|
2021-10-13 20:18:18 +02:00
|
|
|
|
if (m_config_mode == cfg_mode::custom_selection || (m_config_mode == cfg_mode::continuous && !m_config_path.empty()))
|
2019-01-21 21:31:49 +01:00
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
if (fs::file cfg_file{ m_config_path })
|
2020-07-28 19:01:07 +02:00
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
sys_log.notice("Applying %s: %s", m_config_mode, m_config_path);
|
|
|
|
|
|
|
|
|
|
|
|
if (g_cfg.from_string(cfg_file.to_string()))
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.name = m_config_path;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Failed to apply %s: %s", m_config_mode, m_config_path);
|
|
|
|
|
|
}
|
2020-07-28 19:01:07 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
sys_log.fatal("Failed to access %s: %s", m_config_mode, m_config_path);
|
2020-07-28 19:01:07 +02:00
|
|
|
|
}
|
2019-01-21 21:31:49 +01:00
|
|
|
|
}
|
2021-09-22 21:44:52 +02:00
|
|
|
|
else if (m_config_mode == cfg_mode::custom)
|
2019-01-21 21:31:49 +01:00
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
const std::string config_path = rpcs3::utils::get_custom_config_path(m_title_id);
|
2020-07-28 19:01:07 +02:00
|
|
|
|
|
2021-09-22 21:44:52 +02:00
|
|
|
|
// Load custom config-1
|
|
|
|
|
|
if (fs::file cfg_file{ config_path })
|
2021-09-08 14:23:50 +02:00
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
sys_log.notice("Applying custom config: %s", config_path);
|
|
|
|
|
|
|
|
|
|
|
|
if (g_cfg.from_string(cfg_file.to_string()))
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.name = config_path;
|
|
|
|
|
|
m_config_path = config_path;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Failed to apply custom config: %s", config_path);
|
|
|
|
|
|
}
|
2021-09-08 14:23:50 +02:00
|
|
|
|
}
|
2021-09-22 21:44:52 +02:00
|
|
|
|
|
|
|
|
|
|
// Load custom config-2
|
|
|
|
|
|
if (fs::file cfg_file{ m_path + ".yml" })
|
2020-07-28 19:01:07 +02:00
|
|
|
|
{
|
2021-09-22 21:44:52 +02:00
|
|
|
|
sys_log.notice("Applying custom config: %s.yml", m_path);
|
|
|
|
|
|
|
|
|
|
|
|
if (g_cfg.from_string(cfg_file.to_string()))
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.name = m_path + ".yml";
|
|
|
|
|
|
m_config_path = g_cfg.name;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.fatal("Failed to apply custom config: %s.yml", m_path);
|
|
|
|
|
|
}
|
2020-07-28 19:01:07 +02:00
|
|
|
|
}
|
2019-01-21 21:31:49 +01:00
|
|
|
|
}
|
2022-05-07 14:48:46 +02:00
|
|
|
|
|
|
|
|
|
|
// Force audio provider
|
|
|
|
|
|
if (m_path.ends_with("vsh.self"sv))
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.audio.provider.set(audio_provider::rsxaudio);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
g_cfg.audio.provider.set(audio_provider::cell_audio);
|
|
|
|
|
|
}
|
2017-02-28 12:10:04 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-06-13 13:54:16 +02:00
|
|
|
|
// Set RTM usage
|
2021-11-04 17:44:25 +01:00
|
|
|
|
g_use_rtm = utils::has_rtm() && (((utils::has_mpx() && !utils::has_tsx_force_abort()) && g_cfg.core.enable_TSX == tsx_usage::enabled) || g_cfg.core.enable_TSX == tsx_usage::forced);
|
2019-06-06 20:32:35 +02:00
|
|
|
|
|
2020-02-20 21:52:23 +01:00
|
|
|
|
if (!add_only)
|
2018-06-13 13:54:16 +02:00
|
|
|
|
{
|
2021-09-08 00:09:53 +02:00
|
|
|
|
// Log some extra info in case of boot
|
2021-11-13 16:11:49 +01:00
|
|
|
|
#if defined(HAVE_VULKAN)
|
2020-02-20 21:52:23 +01:00
|
|
|
|
if (g_cfg.video.renderer == video_renderer::vulkan)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("Vulkan SDK Revision: %d", VK_HEADER_VERSION);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
sys_log.notice("Used configuration:\n%s\n", g_cfg.to_string());
|
|
|
|
|
|
|
2021-11-04 17:44:25 +01:00
|
|
|
|
if (g_use_rtm && (!utils::has_mpx() || utils::has_tsx_force_abort()))
|
2020-02-20 21:52:23 +01:00
|
|
|
|
{
|
|
|
|
|
|
sys_log.warning("TSX forced by User");
|
|
|
|
|
|
}
|
2021-09-08 00:09:53 +02:00
|
|
|
|
|
|
|
|
|
|
// Initialize patch engine
|
|
|
|
|
|
g_fxo->need<patch_engine>();
|
|
|
|
|
|
|
|
|
|
|
|
// Load patches from different locations
|
|
|
|
|
|
g_fxo->get<patch_engine>().append_global_patches();
|
|
|
|
|
|
g_fxo->get<patch_engine>().append_title_patches(m_title_id);
|
2018-06-13 13:54:16 +02:00
|
|
|
|
}
|
2017-02-28 12:10:04 +01:00
|
|
|
|
|
2020-10-30 23:52:24 +01:00
|
|
|
|
if (g_use_rtm)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Update supplementary settings
|
|
|
|
|
|
const f64 _1ns = utils::get_tsc_freq() / 1000'000'000.;
|
2021-09-02 19:00:30 +02:00
|
|
|
|
g_rtm_tx_limit1 = static_cast<u64>(g_cfg.core.tx_limit1_ns * _1ns);
|
|
|
|
|
|
g_rtm_tx_limit2 = static_cast<u64>(g_cfg.core.tx_limit2_ns * _1ns);
|
2020-10-30 23:52:24 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-10-20 19:51:47 +02:00
|
|
|
|
// Set bdvd_dir
|
2021-09-13 04:12:51 +02:00
|
|
|
|
std::string bdvd_dir;
|
|
|
|
|
|
|
|
|
|
|
|
if (!add_only)
|
|
|
|
|
|
{
|
2022-07-07 22:00:59 +02:00
|
|
|
|
bdvd_dir = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, rpcs3::utils::get_emu_dir());
|
2021-09-13 04:12:51 +02:00
|
|
|
|
|
2022-07-07 22:00:59 +02:00
|
|
|
|
if (!bdvd_dir.empty())
|
2021-09-13 04:12:51 +02:00
|
|
|
|
{
|
2022-07-07 22:00:59 +02:00
|
|
|
|
if (bdvd_dir.back() != fs::delim[0] && bdvd_dir.back() != fs::delim[1])
|
|
|
|
|
|
{
|
|
|
|
|
|
bdvd_dir.push_back('/');
|
|
|
|
|
|
}
|
2021-09-13 04:12:51 +02:00
|
|
|
|
|
2022-08-08 04:46:32 +02:00
|
|
|
|
if (!fs::is_file(bdvd_dir + "PS3_DISC.SFB"))
|
2022-07-07 22:00:59 +02:00
|
|
|
|
{
|
2022-08-08 04:46:32 +02:00
|
|
|
|
if (fs::get_dir_size(bdvd_dir) == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Ignore empty dir. We will need it later for disc games in dev_hdd0.
|
|
|
|
|
|
sys_log.notice("Ignoring empty vfs BDVD directory: '%s'", bdvd_dir);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Unuse if invalid
|
|
|
|
|
|
sys_log.error("Failed to use custom BDVD directory: '%s'", bdvd_dir);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-07 22:00:59 +02:00
|
|
|
|
bdvd_dir.clear();
|
|
|
|
|
|
}
|
2021-09-13 04:12:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-05-20 13:45:02 +02:00
|
|
|
|
|
2018-03-17 18:41:35 +01:00
|
|
|
|
// Special boot mode (directory scan)
|
2020-02-20 21:52:23 +01:00
|
|
|
|
if (!add_only && fs::is_dir(m_path))
|
2018-03-17 18:41:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
m_state = system_state::ready;
|
|
|
|
|
|
GetCallbacks().on_ready();
|
2022-08-23 12:05:55 +02:00
|
|
|
|
g_fxo->init<ppu_module>();
|
2018-03-17 18:41:35 +01:00
|
|
|
|
vm::init();
|
|
|
|
|
|
m_force_boot = false;
|
|
|
|
|
|
|
|
|
|
|
|
// Force LLVM recompiler
|
|
|
|
|
|
g_cfg.core.ppu_decoder.from_default();
|
|
|
|
|
|
|
2020-12-08 20:22:08 +01:00
|
|
|
|
// Force LLE lib loading mode
|
|
|
|
|
|
g_cfg.core.libraries_control.set_set([]()
|
|
|
|
|
|
{
|
|
|
|
|
|
std::set<std::string> set;
|
|
|
|
|
|
|
|
|
|
|
|
extern const std::map<std::string_view, int> g_prx_list;
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& lib : g_prx_list)
|
|
|
|
|
|
{
|
|
|
|
|
|
set.emplace(std::string(lib.first) + ":lle");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return set;
|
|
|
|
|
|
}());
|
2020-05-30 01:17:34 +02:00
|
|
|
|
|
|
|
|
|
|
// Fake arg (workaround)
|
|
|
|
|
|
argv.resize(1);
|
|
|
|
|
|
argv[0] = "/dev_bdvd/PS3_GAME/USRDIR/EBOOT.BIN";
|
|
|
|
|
|
m_dir = "/dev_bdvd/PS3_GAME";
|
2018-03-24 22:04:17 +01:00
|
|
|
|
|
2022-08-23 12:05:55 +02:00
|
|
|
|
Run(false);
|
|
|
|
|
|
|
|
|
|
|
|
std::string path;
|
|
|
|
|
|
std::vector<std::string> dir_queue;
|
|
|
|
|
|
dir_queue.emplace_back(m_path + '/');
|
2018-03-17 18:41:35 +01:00
|
|
|
|
|
2022-08-23 12:05:55 +02:00
|
|
|
|
{
|
2021-07-27 04:09:20 +02:00
|
|
|
|
if (m_title_id.empty())
|
2020-05-31 22:06:09 +02:00
|
|
|
|
{
|
2021-07-27 04:09:20 +02:00
|
|
|
|
// Check if we are trying to scan vsh/module
|
2021-09-23 20:12:06 +02:00
|
|
|
|
const std::string vsh_path = g_cfg_vfs.get_dev_flash() + "vsh/module";
|
2020-05-31 22:06:09 +02:00
|
|
|
|
|
2021-07-27 04:09:20 +02:00
|
|
|
|
if (IsPathInsideDir(m_path, vsh_path))
|
2020-05-31 22:06:09 +02:00
|
|
|
|
{
|
2021-07-27 04:09:20 +02:00
|
|
|
|
// Memorize path to vsh.self
|
|
|
|
|
|
path = vsh_path + "/vsh.self";
|
2020-05-31 22:06:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-07-27 04:09:20 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Find game update to use EBOOT.BIN from it, also add its directory to scan
|
|
|
|
|
|
if (m_cat == "DG")
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string hdd0_path = vfs::get("/dev_hdd0/game/") + m_title_id;
|
2020-05-31 22:06:09 +02:00
|
|
|
|
|
2021-07-27 04:09:20 +02:00
|
|
|
|
if (fs::is_file(hdd0_path + "/USRDIR/EBOOT.BIN"))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_path = hdd0_path;
|
|
|
|
|
|
dir_queue.emplace_back(m_path + '/');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Memorize path to EBOOT.BIN
|
|
|
|
|
|
path = m_path + "/USRDIR/EBOOT.BIN";
|
|
|
|
|
|
|
|
|
|
|
|
// Try to add all related directories
|
|
|
|
|
|
const std::set<std::string> dirs = GetGameDirs();
|
|
|
|
|
|
dir_queue.insert(std::end(dir_queue), std::begin(dirs), std::end(dirs));
|
|
|
|
|
|
}
|
2021-01-30 16:18:10 +01:00
|
|
|
|
|
2021-07-27 04:09:20 +02:00
|
|
|
|
if (fs::is_file(path))
|
2020-05-30 01:17:34 +02:00
|
|
|
|
{
|
2021-07-27 04:09:20 +02:00
|
|
|
|
// Compile binary first
|
|
|
|
|
|
ppu_log.notice("Trying to load binary: %s", path);
|
2020-05-30 01:17:34 +02:00
|
|
|
|
|
|
|
|
|
|
fs::file src{path};
|
|
|
|
|
|
|
|
|
|
|
|
src = decrypt_self(std::move(src));
|
|
|
|
|
|
|
|
|
|
|
|
const ppu_exec_object obj = src;
|
|
|
|
|
|
|
2022-08-23 12:05:55 +02:00
|
|
|
|
if (obj == elf_error::ok && ppu_load_exec(obj))
|
2020-05-30 01:17:34 +02:00
|
|
|
|
{
|
2022-08-23 12:05:55 +02:00
|
|
|
|
g_fxo->get<ppu_module>().path = path;
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-07-27 04:09:20 +02:00
|
|
|
|
sys_log.error("Failed to load binary '%s' (%s)", path, obj.get_error());
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Workaround for analyser glitches
|
2020-12-09 08:47:45 +01:00
|
|
|
|
ensure(vm::falloc(0x10000, 0xf0000, vm::main));
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-04-07 23:05:18 +02:00
|
|
|
|
if (IsStopped())
|
2021-01-30 14:08:22 +01:00
|
|
|
|
{
|
2021-07-28 23:43:11 +02:00
|
|
|
|
m_path = m_path_old; // Reset m_path to fix boot from gui
|
|
|
|
|
|
GetCallbacks().on_stop(); // Call on_stop to refresh gui
|
2022-08-23 12:05:55 +02:00
|
|
|
|
return game_boot_result::no_errors;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g_fxo->init<named_thread>("SPRX Loader"sv, [this, dir_queue]() mutable
|
|
|
|
|
|
{
|
|
|
|
|
|
if (auto& _main = g_fxo->get<ppu_module>(); !_main.path.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
ppu_initialize(_main);
|
2021-01-30 14:08:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ppu_precompile(dir_queue, nullptr);
|
2018-03-17 18:41:35 +01:00
|
|
|
|
|
|
|
|
|
|
// Exit "process"
|
2022-08-23 12:05:55 +02:00
|
|
|
|
CallFromMainThread([this]
|
2018-03-17 18:41:35 +01:00
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
Emu.Kill(false);
|
2022-08-23 12:05:55 +02:00
|
|
|
|
m_path = m_path_old; // Reset m_path to fix boot from gui
|
2018-03-17 18:41:35 +01:00
|
|
|
|
});
|
2020-02-25 09:51:41 +01:00
|
|
|
|
});
|
2020-02-22 17:40:33 +01:00
|
|
|
|
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::no_errors;
|
2018-03-17 18:41:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-07-12 15:38:19 +02:00
|
|
|
|
// Detect boot location
|
2021-03-07 21:42:38 +01:00
|
|
|
|
const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
|
|
|
|
|
|
const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");
|
2021-07-27 03:54:16 +02:00
|
|
|
|
const bool from_hdd0_game = IsPathInsideDir(m_path, hdd0_game);
|
2021-09-23 20:12:06 +02:00
|
|
|
|
const bool from_dev_flash = IsPathInsideDir(m_path, g_cfg_vfs.get_dev_flash());
|
2021-03-07 21:42:38 +01:00
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
|
// m_path might be passed from command line with differences in uppercase/lowercase on windows.
|
2021-07-27 03:54:16 +02:00
|
|
|
|
if ((!from_hdd0_game && IsPathInsideDir(fmt::to_lower(m_path), fmt::to_lower(hdd0_game))) ||
|
2021-09-23 20:12:06 +02:00
|
|
|
|
(!from_dev_flash && IsPathInsideDir(fmt::to_lower(m_path), fmt::to_lower(g_cfg_vfs.get_dev_flash()))))
|
2021-03-07 21:42:38 +01:00
|
|
|
|
{
|
|
|
|
|
|
// Let's just abort to prevent errors down the line.
|
|
|
|
|
|
sys_log.error("The boot path seems to contain incorrectly cased characters. Please adjust the path and try again.");
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
2020-11-19 21:55:06 +01:00
|
|
|
|
// Mount /dev_bdvd/ if necessary
|
|
|
|
|
|
if (bdvd_dir.empty() && disc.empty())
|
2017-07-12 15:38:19 +02:00
|
|
|
|
{
|
2022-06-21 22:13:22 +02:00
|
|
|
|
std::string sfb_dir;
|
|
|
|
|
|
GetBdvdDir(bdvd_dir, sfb_dir, m_game_dir, elf_dir);
|
2021-10-15 19:59:55 +02:00
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
if (!sfb_dir.empty() && from_hdd0_game)
|
2017-07-12 15:38:19 +02:00
|
|
|
|
{
|
2022-06-21 22:13:22 +02:00
|
|
|
|
// Booting disc game from wrong location
|
|
|
|
|
|
sys_log.error("Disc game %s found at invalid location /dev_hdd0/game/", m_title_id);
|
2021-10-15 19:59:55 +02:00
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
const std::string dst_dir = hdd0_disc + sfb_dir.substr(hdd0_game.size());
|
2021-10-15 19:59:55 +02:00
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
// Move and retry from correct location
|
|
|
|
|
|
if (fs::create_path(fs::get_parent_dir(dst_dir)) && fs::rename(sfb_dir, dst_dir, false))
|
2021-10-15 19:59:55 +02:00
|
|
|
|
{
|
2022-06-21 22:13:22 +02:00
|
|
|
|
sys_log.success("Disc game %s moved to special location /dev_hdd0/disc/", m_title_id);
|
|
|
|
|
|
m_path = hdd0_disc + m_path.substr(hdd0_game.size());
|
|
|
|
|
|
return Load(m_title_id, add_only);
|
2021-10-15 19:59:55 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
sys_log.error("Failed to move disc game %s to /dev_hdd0/disc/ (%s)", m_title_id, fs::g_tls_error);
|
|
|
|
|
|
return game_boot_result::wrong_disc_location;
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-09 12:19:08 +02:00
|
|
|
|
if (bdvd_dir.empty() && disc.empty() && !is_disc_patch)
|
2019-06-01 00:12:30 +02:00
|
|
|
|
{
|
2020-02-20 00:12:00 +01:00
|
|
|
|
// Reset original disc game dir if this is neither disc nor disc patch
|
|
|
|
|
|
m_game_dir = "PS3_GAME";
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-07-14 01:58:22 +02:00
|
|
|
|
// Booting patch data
|
2021-07-01 20:36:16 +02:00
|
|
|
|
if ((is_disc_patch || m_cat == "GD") && bdvd_dir.empty() && disc.empty())
|
2017-02-28 12:10:04 +01:00
|
|
|
|
{
|
2017-07-12 15:38:19 +02:00
|
|
|
|
// Load /dev_bdvd/ from game list if available
|
|
|
|
|
|
if (auto node = games[m_title_id])
|
|
|
|
|
|
{
|
|
|
|
|
|
bdvd_dir = node.Scalar();
|
2017-02-28 12:10:04 +01:00
|
|
|
|
}
|
2017-07-14 01:58:22 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.fatal("Disc directory not found. Try to run the game from the actual game disc directory.");
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2017-07-14 01:58:22 +02:00
|
|
|
|
}
|
2017-02-28 12:10:04 +01:00
|
|
|
|
}
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
2017-07-14 01:58:22 +02:00
|
|
|
|
// Check /dev_bdvd/
|
2017-12-25 21:14:57 +01:00
|
|
|
|
if (disc.empty() && !bdvd_dir.empty() && fs::is_dir(bdvd_dir))
|
2017-02-28 12:10:04 +01:00
|
|
|
|
{
|
2017-07-14 01:58:22 +02:00
|
|
|
|
fs::file sfb_file;
|
|
|
|
|
|
|
2018-09-11 18:02:19 +02:00
|
|
|
|
vfs::mount("/dev_bdvd", bdvd_dir);
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Disc: %s", vfs::get("/dev_bdvd"));
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
2019-06-01 00:12:30 +02:00
|
|
|
|
vfs::mount("/dev_bdvd/PS3_GAME", bdvd_dir + m_game_dir + "/");
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Game: %s", vfs::get("/dev_bdvd/PS3_GAME"));
|
2019-06-01 00:12:30 +02:00
|
|
|
|
|
2020-11-19 21:55:06 +01:00
|
|
|
|
const auto sfb_path = vfs::get("/dev_bdvd/PS3_DISC.SFB");
|
|
|
|
|
|
|
|
|
|
|
|
if (!sfb_file.open(sfb_path) || sfb_file.size() < 4 || sfb_file.read<u32>() != ".SFB"_u32)
|
2017-07-12 15:38:19 +02:00
|
|
|
|
{
|
2020-11-19 21:55:06 +01:00
|
|
|
|
sys_log.error("Invalid disc directory for the disc game %s. (%s)", m_title_id, sfb_path);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-08-22 05:53:28 +02:00
|
|
|
|
const auto game_psf = psf::load_object(fs::file{vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO")});
|
|
|
|
|
|
const auto bdvd_title_id = psf::get_string(game_psf, "TITLE_ID");
|
2017-07-14 01:58:22 +02:00
|
|
|
|
|
2021-10-15 19:59:55 +02:00
|
|
|
|
if (m_title_id.empty())
|
2017-07-12 15:38:19 +02:00
|
|
|
|
{
|
2021-10-15 19:59:55 +02:00
|
|
|
|
// We are most likely booting a binary inside a disc directory
|
|
|
|
|
|
sys_log.error("Booting binary without TITLE_ID inside disc dir of '%s'", bdvd_title_id);
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
2021-10-15 19:59:55 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (bdvd_title_id != m_title_id)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Not really an error just an odd situation
|
|
|
|
|
|
sys_log.error("Unexpected PARAM.SFO found in disc directory '%s' (found '%s')", m_title_id, bdvd_title_id);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Store /dev_bdvd/ location
|
|
|
|
|
|
games[m_title_id] = bdvd_dir;
|
|
|
|
|
|
YAML::Emitter out;
|
|
|
|
|
|
out << games;
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
2021-10-15 19:59:55 +02:00
|
|
|
|
fs::pending_file temp(fs::get_config_dir() + "/games.yml");
|
2021-02-21 20:55:07 +01:00
|
|
|
|
|
2021-10-15 19:59:55 +02:00
|
|
|
|
// Do not update games.yml when TITLE_ID is empty
|
|
|
|
|
|
if (!temp.file || temp.file.write(out.c_str(), out.size()), !temp.commit())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to save BDVD location of title '%s' (%s)", m_title_id, fs::g_tls_error);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
2018-06-23 11:36:16 +02:00
|
|
|
|
else if (m_cat == "1P" && from_hdd0_game)
|
|
|
|
|
|
{
|
2020-02-20 00:12:00 +01:00
|
|
|
|
// PS1 Classic located in dev_hdd0/game
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("PS1 Game: %s, %s", m_title_id, m_title);
|
2018-06-23 11:36:16 +02:00
|
|
|
|
|
2020-03-26 16:32:22 +01:00
|
|
|
|
const std::string game_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size(), 9);
|
2018-06-23 11:36:16 +02:00
|
|
|
|
|
|
|
|
|
|
argv.resize(9);
|
|
|
|
|
|
argv[0] = "/dev_flash/ps1emu/ps1_newemu.self";
|
|
|
|
|
|
argv[1] = m_title_id + "_mc1.VM1"; // virtual mc 1 /dev_hdd0/savedata/vmc/%argv[1]%
|
|
|
|
|
|
argv[2] = m_title_id + "_mc2.VM1"; // virtual mc 2 /dev_hdd0/savedata/vmc/%argv[2]%
|
|
|
|
|
|
argv[3] = "0082"; // region target
|
|
|
|
|
|
argv[4] = "1600"; // ??? arg4 600 / 1200 / 1600, resolution scale? (purely a guess, the numbers seem to match closely to resolutions tho)
|
2020-03-26 16:32:22 +01:00
|
|
|
|
argv[5] = game_path; // ps1 game folder path (not the game serial)
|
2018-06-23 11:36:16 +02:00
|
|
|
|
argv[6] = "1"; // ??? arg6 1 ?
|
|
|
|
|
|
argv[7] = "2"; // ??? arg7 2 -- full screen on/off 2/1 ?
|
|
|
|
|
|
argv[8] = "1"; // ??? arg8 2 -- smoothing on/off = 1/0 ?
|
|
|
|
|
|
|
|
|
|
|
|
//TODO, this seems like it would normally be done by sysutil etc
|
|
|
|
|
|
//Basically make 2 128KB memory cards 0 filled and let the games handle formatting.
|
|
|
|
|
|
|
|
|
|
|
|
fs::file card_1_file(vfs::get("/dev_hdd0/savedata/vmc/" + argv[1]), fs::write + fs::create);
|
|
|
|
|
|
card_1_file.trunc(128 * 1024);
|
|
|
|
|
|
fs::file card_2_file(vfs::get("/dev_hdd0/savedata/vmc/" + argv[2]), fs::write + fs::create);
|
|
|
|
|
|
card_2_file.trunc(128 * 1024);
|
|
|
|
|
|
}
|
2020-03-26 18:03:00 +01:00
|
|
|
|
else if (m_cat == "PE" && from_hdd0_game)
|
|
|
|
|
|
{
|
|
|
|
|
|
// PSP Remaster located in dev_hdd0/game
|
|
|
|
|
|
sys_log.notice("PSP Remaster Game: %s, %s", m_title_id, m_title);
|
|
|
|
|
|
|
|
|
|
|
|
const std::string game_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size(), 9);
|
|
|
|
|
|
|
|
|
|
|
|
argv.resize(2);
|
|
|
|
|
|
argv[0] = "/dev_flash/pspemu/psp_emulator.self";
|
|
|
|
|
|
argv[1] = game_path;
|
|
|
|
|
|
}
|
2017-12-25 21:14:57 +01:00
|
|
|
|
else if (m_cat != "DG" && m_cat != "GD")
|
2017-10-31 22:23:09 +01:00
|
|
|
|
{
|
2017-12-25 21:14:57 +01:00
|
|
|
|
// Don't need /dev_bdvd
|
2017-10-31 22:23:09 +01:00
|
|
|
|
}
|
2022-07-07 20:06:28 +02:00
|
|
|
|
else if (m_cat == "DG" && from_hdd0_game && disc.empty())
|
2018-03-11 11:05:47 +01:00
|
|
|
|
{
|
2020-02-20 00:12:00 +01:00
|
|
|
|
// Disc game located in dev_hdd0/game
|
2022-07-07 22:00:59 +02:00
|
|
|
|
bdvd_dir = g_cfg_vfs.get(g_cfg_vfs.dev_bdvd, rpcs3::utils::get_emu_dir());
|
|
|
|
|
|
|
2022-08-08 04:46:32 +02:00
|
|
|
|
if (fs::get_dir_size(bdvd_dir))
|
2022-07-07 22:00:59 +02:00
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to load disc game from dev_hdd0. The virtual bdvd_dir path does not exist or the directory is not empty: '%s'", bdvd_dir);
|
|
|
|
|
|
return game_boot_result::invalid_bdvd_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vfs::mount("/dev_bdvd", bdvd_dir);
|
2018-09-11 18:02:19 +02:00
|
|
|
|
vfs::mount("/dev_bdvd/PS3_GAME", hdd0_game + m_path.substr(hdd0_game.size(), 10));
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Game: %s", vfs::get("/dev_bdvd/PS3_GAME"));
|
2018-03-11 11:05:47 +01:00
|
|
|
|
}
|
|
|
|
|
|
else if (disc.empty())
|
2017-07-14 01:58:22 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to mount disc directory for the disc game %s", m_title_id);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2017-07-14 01:58:22 +02:00
|
|
|
|
}
|
2018-03-11 11:05:47 +01:00
|
|
|
|
else
|
2017-12-25 21:14:57 +01:00
|
|
|
|
{
|
2020-02-20 00:12:00 +01:00
|
|
|
|
// Disc game
|
2017-12-25 21:14:57 +01:00
|
|
|
|
bdvd_dir = disc;
|
2018-09-11 18:02:19 +02:00
|
|
|
|
vfs::mount("/dev_bdvd", bdvd_dir);
|
2022-07-09 12:19:08 +02:00
|
|
|
|
vfs::mount("/dev_bdvd/PS3_GAME", bdvd_dir + m_game_dir);
|
|
|
|
|
|
sys_log.notice("Disk: %s, Dir: %s", vfs::get("/dev_bdvd"), m_game_dir);
|
2017-12-25 21:14:57 +01:00
|
|
|
|
}
|
2017-07-12 15:38:19 +02:00
|
|
|
|
|
2017-08-06 21:29:28 +02:00
|
|
|
|
if (add_only)
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Finished to add data to games.yml by boot for: %s", m_path);
|
2019-01-06 23:30:38 +01:00
|
|
|
|
m_path = m_path_old; // Reset m_path to fix boot from gui
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::no_errors;
|
2017-08-06 21:29:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-09-08 00:09:53 +02:00
|
|
|
|
// Initialize progress dialog
|
|
|
|
|
|
g_fxo->init<named_thread<progress_dialog_server>>();
|
|
|
|
|
|
|
2022-03-11 21:08:44 +01:00
|
|
|
|
// Initialize performance monitor
|
|
|
|
|
|
g_fxo->init<named_thread<perf_monitor>>();
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
// Set title to actual disc title if necessary
|
|
|
|
|
|
const std::string disc_sfo_dir = vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO");
|
|
|
|
|
|
|
|
|
|
|
|
const auto disc_psf_obj = psf::load_object(fs::file{ disc_sfo_dir });
|
|
|
|
|
|
|
2017-09-13 01:49:02 +02:00
|
|
|
|
// Install PKGDIR, INSDIR, PS3_EXTRA
|
|
|
|
|
|
if (!bdvd_dir.empty())
|
|
|
|
|
|
{
|
2021-08-19 07:49:59 +02:00
|
|
|
|
std::string ins_dir = vfs::get("/dev_bdvd/PS3_GAME/INSDIR/");
|
|
|
|
|
|
std::string pkg_dir = vfs::get("/dev_bdvd/PS3_GAME/PKGDIR/");
|
|
|
|
|
|
std::string extra_dir = vfs::get("/dev_bdvd/PS3_GAME/PS3_EXTRA/");
|
2017-09-13 01:49:02 +02:00
|
|
|
|
fs::file lock_file;
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
for (const auto path_ptr : {&ins_dir, &pkg_dir, &extra_dir})
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2021-08-19 07:49:59 +02:00
|
|
|
|
if (!fs::is_dir(*path_ptr))
|
|
|
|
|
|
{
|
|
|
|
|
|
path_ptr->clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const std::string lock_file_path = fmt::format("%s%s%s_v%s", hdd0_game, u8"$locks/", m_title_id, psf::get_string(disc_psf_obj, "APP_VER"));
|
|
|
|
|
|
|
|
|
|
|
|
if (!ins_dir.empty() || !pkg_dir.empty() || !extra_dir.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
// For backwards compatibility
|
|
|
|
|
|
if (!lock_file.open(hdd0_game + ".locks/" + m_title_id))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Check if already installed
|
|
|
|
|
|
lock_file.open(lock_file_path);
|
|
|
|
|
|
}
|
2017-09-13 01:49:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
if (!lock_file && !ins_dir.empty())
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Found INSDIR: %s", ins_dir);
|
2017-09-13 01:49:02 +02:00
|
|
|
|
|
|
|
|
|
|
for (auto&& entry : fs::dir{ins_dir})
|
|
|
|
|
|
{
|
2019-06-01 00:12:30 +02:00
|
|
|
|
const std::string pkg = ins_dir + entry.name;
|
2021-04-21 22:12:21 +02:00
|
|
|
|
if (!entry.is_directory && entry.name.ends_with(".PKG") && !rpcs3::utils::install_pkg(pkg))
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to install %s", pkg);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::install_failed;
|
2017-09-13 01:49:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
if (!lock_file && !pkg_dir.empty())
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Found PKGDIR: %s", pkg_dir);
|
2017-09-13 01:49:02 +02:00
|
|
|
|
|
|
|
|
|
|
for (auto&& entry : fs::dir{pkg_dir})
|
|
|
|
|
|
{
|
2020-02-17 22:43:23 +01:00
|
|
|
|
if (entry.is_directory && entry.name.starts_with("PKG"))
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
|
|
|
|
|
const std::string pkg_file = pkg_dir + entry.name + "/INSTALL.PKG";
|
|
|
|
|
|
|
2021-04-21 22:12:21 +02:00
|
|
|
|
if (fs::is_file(pkg_file) && !rpcs3::utils::install_pkg(pkg_file))
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to install %s", pkg_file);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::install_failed;
|
2017-09-13 01:49:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
if (!lock_file && !extra_dir.empty())
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Found PS3_EXTRA: %s", extra_dir);
|
2017-09-13 01:49:02 +02:00
|
|
|
|
|
|
|
|
|
|
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";
|
|
|
|
|
|
|
2021-04-21 22:12:21 +02:00
|
|
|
|
if (fs::is_file(pkg_file) && !rpcs3::utils::install_pkg(pkg_file))
|
2017-09-13 01:49:02 +02:00
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to install %s", pkg_file);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::install_failed;
|
2017-09-13 01:49:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2021-08-19 07:49:59 +02:00
|
|
|
|
|
|
|
|
|
|
if (!lock_file)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Create lock file to prevent double installation
|
|
|
|
|
|
// Do it after installation to prevent false positives when RPCS3 closed in the middle of the operation
|
|
|
|
|
|
lock_file.open(lock_file_path, fs::read + fs::create + fs::excl);
|
|
|
|
|
|
}
|
2017-09-13 01:49:02 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-07-12 15:38:19 +02:00
|
|
|
|
// Check game updates
|
|
|
|
|
|
const std::string hdd0_boot = hdd0_game + m_title_id + "/USRDIR/EBOOT.BIN";
|
|
|
|
|
|
|
2022-07-30 05:39:19 +02:00
|
|
|
|
if (!m_ar && disc.empty() && !bdvd_dir.empty() && !m_title_id.empty() && resolved_path == GetCallbacks().resolve_path(vfs::get("/dev_bdvd/PS3_GAME/USRDIR/EBOOT.BIN")) && resolved_path != GetCallbacks().resolve_path(hdd0_boot) && fs::is_file(hdd0_boot))
|
2017-07-12 15:38:19 +02:00
|
|
|
|
{
|
|
|
|
|
|
// Booting game update
|
2020-11-19 23:41:16 +01:00
|
|
|
|
sys_log.success("Updates found at /dev_hdd0/game/%s/", m_title_id);
|
2022-06-21 22:13:22 +02:00
|
|
|
|
m_path = hdd0_boot;
|
|
|
|
|
|
return Load(m_title_id, false, true);
|
2017-07-12 15:38:19 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-08-19 07:49:59 +02:00
|
|
|
|
if (!disc_psf_obj.empty())
|
2019-07-19 22:49:22 +02:00
|
|
|
|
{
|
2021-08-19 07:49:59 +02:00
|
|
|
|
const auto bdvd_title = psf::get_string(disc_psf_obj, "TITLE");
|
2019-07-19 22:49:22 +02:00
|
|
|
|
|
|
|
|
|
|
if (!bdvd_title.empty() && bdvd_title != m_title)
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Title was set from %s to %s", m_title, bdvd_title);
|
2019-07-19 22:49:22 +02:00
|
|
|
|
m_title = bdvd_title;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (auto& c : m_title)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Replace newlines with spaces
|
|
|
|
|
|
if (c == '\n')
|
|
|
|
|
|
c = ' ';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-09-11 18:02:19 +02:00
|
|
|
|
// Mount /host_root/ if necessary (special value)
|
2017-05-20 13:45:02 +02:00
|
|
|
|
if (g_cfg.vfs.host_root)
|
2017-02-28 12:10:04 +01:00
|
|
|
|
{
|
2018-09-11 18:02:19 +02:00
|
|
|
|
vfs::mount("/host_root", "/");
|
2017-02-28 12:10:04 +01:00
|
|
|
|
}
|
2013-09-24 23:11:29 +02:00
|
|
|
|
|
2017-07-12 18:35:46 +02:00
|
|
|
|
// Open SELF or ELF
|
2018-06-23 16:30:16 +02:00
|
|
|
|
std::string elf_path = m_path;
|
|
|
|
|
|
|
2020-03-26 18:03:00 +01:00
|
|
|
|
if (m_cat == "1P" || m_cat == "PE")
|
2018-06-23 16:30:16 +02:00
|
|
|
|
{
|
|
|
|
|
|
// Use emulator path
|
|
|
|
|
|
elf_path = vfs::get(argv[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (m_ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_tls_log_prefix = []()
|
|
|
|
|
|
{
|
|
|
|
|
|
return fmt::format("Emu State Load Thread: '%s'", g_tls_serialize_name);
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-06-23 16:30:16 +02:00
|
|
|
|
fs::file elf_file(elf_path);
|
2017-07-12 18:35:46 +02:00
|
|
|
|
|
|
|
|
|
|
if (!elf_file)
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to open executable: %s", elf_path);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
|
|
|
|
|
if (m_ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.warning("State Inspection Savestate Mode!");
|
|
|
|
|
|
|
|
|
|
|
|
vm::init();
|
|
|
|
|
|
vm::load(*m_ar);
|
|
|
|
|
|
|
|
|
|
|
|
if (!hdd1.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
vfs::mount("/dev_hdd1", hdd1);
|
|
|
|
|
|
sys_log.notice("Hdd1: %s", hdd1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
init_fxo_for_exec(DeserialManager(), true);
|
|
|
|
|
|
|
|
|
|
|
|
return game_boot_result::no_errors;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2017-07-12 18:35:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-11 19:06:57 +01:00
|
|
|
|
// Check SELF header
|
|
|
|
|
|
if (elf_file.size() >= 4 && elf_file.read<u32>() == "SCE\0"_u32)
|
2015-04-24 02:35:42 +02:00
|
|
|
|
{
|
2019-01-13 18:06:30 +01:00
|
|
|
|
const std::string decrypted_path = "boot.elf";
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
2017-02-22 13:21:30 +01:00
|
|
|
|
fs::stat_t encrypted_stat = elf_file.stat();
|
|
|
|
|
|
fs::stat_t decrypted_stat;
|
2017-02-11 19:06:57 +01:00
|
|
|
|
|
2017-02-22 13:21:30 +01:00
|
|
|
|
// Check modification time and try to load decrypted ELF
|
2019-01-13 18:06:30 +01:00
|
|
|
|
if (false && fs::stat(decrypted_path, decrypted_stat) && decrypted_stat.mtime == encrypted_stat.mtime)
|
2016-04-14 00:59:00 +02:00
|
|
|
|
{
|
2017-02-22 13:21:30 +01:00
|
|
|
|
elf_file.open(decrypted_path);
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2018-06-22 10:49:40 +02:00
|
|
|
|
// Decrypt SELF
|
2020-12-21 15:12:05 +01:00
|
|
|
|
else if ((elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : reinterpret_cast<u8*>(&klic[0]), &g_ps3_process_info.self_info)))
|
2016-04-14 00:59:00 +02:00
|
|
|
|
{
|
2019-01-13 18:06:30 +01:00
|
|
|
|
if (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (fs::file elf_out{decrypted_path, fs::rewrite})
|
2017-02-22 13:21:30 +01:00
|
|
|
|
{
|
|
|
|
|
|
elf_out.write(elf_file.to_vector<u8>());
|
|
|
|
|
|
elf_out.close();
|
|
|
|
|
|
fs::utime(decrypted_path, encrypted_stat.atime, encrypted_stat.mtime);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to create boot.elf");
|
2017-02-22 13:21:30 +01:00
|
|
|
|
}
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2017-02-22 13:21:30 +01:00
|
|
|
|
}
|
2019-11-01 20:21:15 +01:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
g_ps3_process_info.self_info.valid = false;
|
|
|
|
|
|
}
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
|
|
|
|
|
if (!elf_file)
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Failed to decrypt SELF: %s", elf_path);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::decryption_error;
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2018-06-22 10:49:40 +02:00
|
|
|
|
|
2021-03-30 18:37:51 +02:00
|
|
|
|
m_state = system_state::ready;
|
|
|
|
|
|
|
2018-06-22 10:49:40 +02:00
|
|
|
|
ppu_exec_object ppu_exec;
|
|
|
|
|
|
ppu_prx_object ppu_prx;
|
2022-04-27 18:46:09 +02:00
|
|
|
|
ppu_rel_object ppu_rel;
|
2018-06-22 10:49:40 +02:00
|
|
|
|
spu_exec_object spu_exec;
|
2022-04-27 18:46:09 +02:00
|
|
|
|
spu_rel_object spu_rel;
|
2018-06-22 10:49:40 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
vm::init();
|
|
|
|
|
|
|
|
|
|
|
|
if (m_ar)
|
|
|
|
|
|
{
|
|
|
|
|
|
vm::load(*m_ar);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!hdd1.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
vfs::mount("/dev_hdd1", hdd1);
|
|
|
|
|
|
sys_log.notice("Hdd1: %s", vfs::get("/dev_hdd1"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-06-22 10:49:40 +02:00
|
|
|
|
if (ppu_exec.open(elf_file) == elf_error::ok)
|
2016-04-14 00:59:00 +02:00
|
|
|
|
{
|
|
|
|
|
|
// PS3 executable
|
RPCS3 QT (#2645)
* Fix windows build. I made sure to do everything with a win32 prefix to not effect linux build.
* Make the window resizable instead of fixed in the corner.
* Ignore moc files and things in the debug/release folder. I might also ignore rpcs3qt.vcxproj and its filters as they're autogenerated by importing the qt project file. But, this helps clean out clutter for now.
* Add cmake. This doesn't interact with the rest of rpcs3 nor the main cmake file. That's the next thing I'm doing. I'll probably need to modify them so it'll take me time to figure out. But, this will build rpcs3qt on linux and build as is with using qt.
* The build works. I'd like to thank my friends, Google and Stackoverflow.
Setted up by importing rpcs3Qt project using Qt's visual studio plugin.
* Cleanup. Remove all the stuff in the rpcs3qt folder as its incorporated elsewhere. Remove the rpcs3qt project file as its now built into the solution and cmake doesn't care about pro files.
* Update readme to reflect getting Qt.
* Remove wxwidgets as submodule and add zlib instead. Wxwidgets was our old way of having zlib. I also added build dependencies to rpcs3qt so you should no longer get link errors on the first clean rebuild.
* Add rpcs3_version, few GUI tweaks
* Set defaultSize to 70% of screen size
* Add the view menu (#3)
* Added the view menu with the corresponding elements. Now, the debugger/log are hidden by default. The view menu has a checkbox which you click to show/hide the dock widgets.
* Make log visible by default
* Improve UI by making it into a checkbox that's easier to use.
* fix qt build for vs2017 (seems to work fine in 2015 with plugin but needs testing by other users)
* updated readme for qt
* update appveyor for qt
- cleaned formatting for the post build command
* fix build (#6)
* fix build legit this time i promise
* [Ready] Gamepadsettings (#4)
* WIP Gamepadsettings
pushbutton Eventhandling missing
* GamepadSettings should work except for cfg Init
Some KeyInputs are missing
* Update padsettingsdialog.h
* Update padsettingsdialog.cpp (#5)
* Update padsettingsdialog.cpp
removed silly tabs
* Update padsettingsdialog.cpp
* GetKeyCode simplified
* rename pad settings to keyboard settings o.O
* rename keyboard setting to input settings
* Remvoed the QT_UI defines.
* Readded new line at end of file. Replaced define in padsettings with constant.
* GUI fixes (Settings)
* Stub the logger UI. Nothing special besides a simple stub.
* Unstub the log. I haven't tested TTY but it should work.
Only thing to do, but this is in general, is add persistent settings.
* Minor refactoring to simplify code.
* Fix image loading. I'm 90% sure it works because it loads the path as expected and that's the same format I used in my gamelist implementation for the images.
* Made game lists much more functional than it was.
* mainwindow
* gamelist
* Please forgive me for I have lambdaed.
Added the ability to toggle showing columns via a context menu.
* Fix GameList further
* sort by name on init fixed
* Created the baseline refactoring. I'm going to start working on the callbacks now. May need to implement other classes in the process. Fun stuff, I know.
* adds InstallPkg (tested) and InstallPup (should work but makes unknown shenanigans) implementation
adds RefreshGameList
obliterates 10sec Refresh
* messages
* Rpcs3 gs frame (#16)
* Messing with project settings try to get trails of cold steel to boot.bluh
Definitely one change is needed in linker settings for RPCS3 to not crash immediately.
Can't even see how horribly botched my implementation of GSFrame is because we aren't booting lol. Something is gone awry with elf.
* remove random ! not that it matters much right now
* minor additions
* "Working" with debug mode though you have to ignore an assert reached from Qt. Qt is upset that the rsx thread is calling stuff on the UI thread despite not owning it. However, I can't do a thing to change that atm. (The fix would be to do what the TODO says in System.cpp-- making gsframe and stuff get initialized via system call)
Crashes due to needing pad callback to be done.
* With this build in debug mode, Trails of Cold steel will get FPS. (caveat. You have to ignore when Qt throws a debug assert lol)
* Fix release mode. Fix the Qt debug assert by using ancient occault rituals. I want to be able to remove the blocking connects but it won't work right now without it. It isn't perfect but it's good enough for now IMO.
* Add enters to the end of files.
* Removing target and setting source of events to be the application instead of the main window. The main window isn't the game window, and I don't really know what widget will be targetted for the game event. Works, though, it's admittedly probably not optimal by ANY means.
* Fix comment.
* Fix libpng wit zlib.
* Move Qt GUI into RPCS3Qt. (#17)
Restore wx GUI.
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* Add stylesheet to git ignore.
* XInput..
* Joystick...
* Rpcs3 qt small fixes (#20)
* Small fixes. Have emulator stop when x button is pressed on game window. Have emulator/application stop when the main window is closed.
* If I forget another new line ending for a file.............................................
* Add CgDisasm (#21)
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* add CgDisasm
add code to disable contextmenu options
fix gamelist issue
* missing proj changes
* Add ability to open stylesheets from menu.
* Mega searcher (#23)
* add MemoryStringSearcher
set minimum Sizes for mainwindow and CgDisasm
* minor fixes
* Since the system.cpp callbacks for emulator state were unused, I removed them. Then, I replaced them with callbacks for the Gui.
* added stylesheet options
setfocus on settings fixed
newline added
* added signals and slots for EmuRun and EmuStop
* update ui
update ui now works
added callback onReady
added EnableMenues
added ps3 commands
* added restart logic to menu
* newline
* event header removed
* Added graphic settings class. (#26)
* Added graphic settings class. First thing is to have the dock widgets and window size/location be stateful. Minor bug with debugger frame changing size on hide/show on default setup on second load. But, otherwise, fine. Also, the GUI doesn't update to accomodate the statefulness of the widgets. But, that'll come in time as I update this class.
* Add view debugger, logger, gamelist to settings and synchronize them.
* Separate initializing actions from connects
* Add invisible fullscreen cursor and double click event.
* Add the UI log settings.
* Add MemoryViewer (#30)
* Add Memoryviewer
Image Button crashes/not fully implemented
focus on some button annoying
minor changes for question dialogs
* GuiSettings Refactoring (#31)
* Add settings for columns shown and which one is saved
* I accidentally refactored the settings class. Added ability to reset to default GUI. Added statefulness to column widths.
* add gui tab
* Fix logging at startup.
* Preset settings.I think I ironed out MOST of the glitches. Will work on the rest of it soon. Should be a lot simpler as I won't have to use the so-called meta settings. Also, renamed all settings methods to CapitalCase.
* Removed dock widget controls.
* Added style sheets. Removed the option from the menu.
* Rewrite to use folder design. Much simpler! Yay! Simpler. Better, right?
* It's remarkable how tricky this is.
* Added convenience button to open up the settings folder in explorer
* Add newlines at end of file
* simplified logic. Fixed a bug.. hopefully not more bugs
* Fix the undocumented feature
* Make the dialog big enough to have entire text on title shown. If talkashie changes the font to size 1203482 I don't care lol
* Make warning messagebox instead of changing the title of the dialog.
* marking...
* Hcorion suggested changes.
* [WIP] autopause (#32)
* autopause added
needs fixing
headers do not show text
* fix compile stuff
* Add MsgDialog + edge widgets (#33)
* Add MsgDialog
needs magic
* add "Debugger" Buttons to menubar
* Adapt ds4 changes. I'm not sure if they work as I don't have a compatible controller. But, at the same time, it's kind of silly all I had to do was remove stdguiafx to get compilation.
* [Ready] Add KernelExplorer (#36)
* KernelExplorer added
* Fix build. Connect mainwindow to show explorer.
* qstr formatting added
hid header, fixed button size
* Taskbar Progress for install PUP/PKG (#37)
* Add Taskbar Progress for both PKG and PUP installer
* fix missing ifdefs for windows
* add mainwindow icon + thumbnail toolbar
* add game specific icons to the GSFrame
* fix icon crash
* fix appIcon's aspect ratio in SetAppIconFromPath
* Fix black borders in RGB32 icons
* rename thumbar related buttons
* EmuSettings (#35)
* Core tab done minus doing the library list.
* Graphics tab.
* Audio tab
* Input tab
* Added the other tabs
* LLE part one-- load existing libraries sorted. (I'd finish it but I'm going to look at a PR by mega)
* add search and add other libraries that aren't checked.
* Finish adding lle selecting things.
* marking my territory (#38)
fixed settingsdialog glitch and width
added groupbox to gui buttons
removed parents from layouts
* add debuggerframe + RSXDebugger (#34)
* Add Debuggerframe
* add RSXDebugger
* add RSXDebugger fo real
* RSXDebugger improved
minor adjustments
* add utf8 conversions like neko told me to
hopefully i did not utf8-ise too many things xD
* fix some variables
* maybe fix image buffers in RSXDebugger
* fixed image view (pretty sure)
* fixed image buffer (hopefully)
* QT Opengl frame (#41)
* fix RSX Debugger headers (#40)
* fix some debugger layout issues
fix RSX Debugger headers + some comments
* add kd-11's SPU options
fix D3D12 showing on non-compatible systems
tidy up coretab
* improve D3D12 behaviour in graphicstab:
adapter selection and D3D12 render won't show on non-compatible systems
add monospace font to cgDisasm
* enable update only on visibility
* Rpcs3 qt llvm build (#42)
* LLVM pushed so mega can test
* probably is what is needed with Release LLVM
* should probably have RPCS3-Qt be using release-llvm
* include zlib the same way.
* don't talk to me about how I made this happen.
* I applied the magical treatment to debug mode too. Though, it's entirely probably that doing it once in LLVM-release mode made this entirely redundant
* hack
* progress bar for LLVM spawns but doesn't close yet.
* fix msgDialog (#43)
fix oskDialog
* Minor bug fixzz
* fix osk and msgdialog for real (#44)
* fix msgDialog
fix oskDialog
* fix OskDialog part 2
fix MsgDialog part 2
* This bug is evil, and it should be ashamed of itself.
* Refactor YAML. Commented out gui options that aren't added to config yet (add em back later when we merge that in)
* Fix pad stuff.
* add SaveDataUtility (#45)
* add SaveDataUtility
* fix slots
* fix slots again
fix lists not showing stuff
fix dialogs not showing
add colClicked
refactor stuff and polish some layouts
* add SaveDataDialog.h and SaveDataDialog.cpp
* tidy up mainwindow
* add callback
* fix RegisterEditor (#47)
* fix RegisterEditor
* fix other dialogs' immortality (gasp...vampires)
* remove debug leftovers
* fix InstructionEditor (#46)
* fix InstructionEditor
* fix typo
* Fix MouseClickEvents in RSXDebugger (#50)
* Fix MouseClickEvents in RSXDebugger
Fix focus on MemoryViewer and RSXDebugger
Adjust PadButtonWidth
* fix another comment
* fix debuggerframe events (#49)
* Fix pad settings bro (#48)
* Fix pad settings bro
* fix comment
* Icons and Menu-Additions (#39)
* Add Icons and iconlogic to cornerWidget and actions
* add cornerWidget toggle
fix dockwidget action state on start
remove DoSettings
* fix game removal bug
remove tableitem focus rectangle
therefore add TableItemDelegate.h
* remove grid and focus rectangle from autopausedialog
* add fullscreen checkbox to misctab
minor padsettings layout improvements
* Add show category submenu to view menu
Add gamelist filter accordingly
fix minor bug where play icon was displayed despite pause label
add boolean b_fullscreen to mainwindow for later use in GSFrame
* fix headers in autopausesettings
fix remove bug in autopausesettings
add delete keypressevent in autopausesettings
fix missing tr() and minor refactoring in gamelist
* add default Icons for play/pause/stop/restart
* Fix fullscreen start. Some stuff was wrong with settings, just trust me.
* remove fullscreen leftovers and fix merge
* SPU stuff. (There was also a weird thing with config.h in GLGSFrame.h with an include that I removed to fix build)
* please neko's lambda fetishes (#53)
* please neko's lambda fetish in mainwindow
* please neko's lambda fetish in gamelistframe
* please neko's lambda fetish in logframe
* fix neko's lambda fetish in debuggerframe
* pleasefixdofetishsomething in Autopausesettingsdialog
* fix sth sth lambda in cg disasm
* lambda stuff in instructioneditor
* lambda kernelexplorer
* lambda-ise memoryviewer
* lambda rsxdebugger
* lambda savedatautil
this could be done even more, but the functions are not implemented
* Rpcs3 qt fixes -- shadow taskbar bug (#52)
* SShadow's bug of taskbar progress staying fixed on cancelling pkg install.
* other taskbar
* i'm still a baka
* Fix a warning
* qtQt refactoring (#54)
* fix neko's snake fetish
* File names should match headers. Are these the names I want? Not necessarily. But, this is much less confusing.
* i thought I committed everything with stage all.........................
* remove unused utilities
* The most important commit of them all.
* Disable legacy opengl buffers when not using opengl.
* fix code review comment
* Quick crash patch. Neko removed autopause. SO, I remove it too from emusettings/misc tab
* Merge lovely things from master (#55)
* Configuration simplified
* untrivial parts of the merge
* no need for these options anymore
* Minor change to fix column widths at startup (not sure why it doesn't work already, but adding the true makes it work so......... whatever)
* here ya go
* FIx hitting okay in settings causing graphics to messup (#57)
* fixes + msgdialog taskbarprogress (#56)
* fix ok button in taskbar
add taskicon progressbar for msgdialog
add tablewidgetitem to rsxdebugger
fix comments in save_data_utility.cpp
* fix d3d adapter default
* fix taskicon progressbar not being destroyed properly
* add last_path to filedialogs
* fix msgdialog crash on ok (#58)
* fix thread stopping in debbugerFrame (#59)
* Move Emu.init to be first. This will fix the qt stuff seeming to ignore the virtual filesystem in the config. (VFS to be made soon maybe) (#60)
* Fix full screen opening on double RIGHT click.
* fix other instances of double click ...
* Fix locaiton of gui config. (#61)
* fix d3d bug (#62)
* fix d3d bug
* small utf8 addition
* Fix cmake for qt (#64)
* Initial CMake fix
* Fix compilation with GCC
* Get rid of awful hack
* Update cotire with qt support
* Maybe fix travis
* Emergency Hack Relief Program Activated
* Fix travis build (#65)
* make about dialog great again (#67)
and add previous additions
* Fix library sort / smart gamelist context menu (#63)
* fix library sort
* add Title to custom game config dialog
* disable options on gamelist context menu
* use namespace for category Strings
* introduce sstr
* fix some tr nonsense
* Rpcs3qt Appveyor (#68)
Fix appyveyor build!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* possible fix for gamelist icons (#69)
add warning for appicon
* Fix clang build (#66)
Hcorion, the build savior.
* Rpcs3 qt resources (#70)
* Resource files attempt 1
* Autorcc should probably be on?
* forgot the most important file lol
* Forgot an instance of the icon in the code...
* Patch fix for clang build.
* vulkan/d3d12 combobox merge (#71)
* add vulkan adapterbox and merge with d3d12 box
* fix adapter text on other renderer
* gather render strings
* attempt fix on gamelist row height
* adjust adapter behaviour to new guideline
* Compiler of Peace.
* High critical hit rate.
* Mugi eating strawberries is savage.
* Apply KD-11 Hotfix (#73)
* Most of Ani Adjusts (#72)
* Most of the adjustments are made here.
* fix gamelist rowheight
* fix msg dialog layout and disable_cancel
* cleanup
* fix disable cancle again
* fix debuggerframe buttons and doubleclick
* Add a fun little bonus feature :) (#74)
* category filters simplyfied (#75)
* Cleaning up cmake a bit.
* fixezzzzzz (#76)
* upgrade Info Boxes
* upgrade file explorer
* refactor GetSettings and SetSettings
* second refactoring
* cleanup
* travis is a grammar nazi
* second travis shenanigans
* third travis weirdo thingy
* travis 4 mega fun
* travis 5 default to def
* finish refactoring for settings
fix gamelist headers
* hotfix msgdialog and infobox (#77)
* msgdialog fix 1
* fix zombie infobox
* Rpcs3 Qt Welcome Page (#78)
* Add a welcome dialog.
* Add enter to end of file
* i'm an idiot
* last mistake i hope
* sponsored via --> funded by
* RPCS3 does not condone piracy.
* Mega Adjusts
* Ani Adjustments and a few refactorings
* Yay
* Add Gamelist Icon Sizes (#79)
* Reverting Mega's suggestion. If people can use alt-f4 to get around this dialog, they can probably use an emulator too.
* Fix firmware file choice dialog in QT GUI (#80)
* ani adjusts 2 + minor icon size simplifications (#81)
FPS Additions
* Update Travis to Qt 5.9 (#82)
2017-06-04 16:48:33 +02:00
|
|
|
|
GetCallbacks().on_ready();
|
|
|
|
|
|
|
2017-09-18 18:16:36 +02:00
|
|
|
|
if (argv.empty())
|
2017-10-12 16:58:06 +02:00
|
|
|
|
{
|
|
|
|
|
|
argv.resize(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (argv[0].empty())
|
2016-04-14 00:59:00 +02:00
|
|
|
|
{
|
2021-04-06 22:16:58 +02:00
|
|
|
|
auto unescape = [](std::string_view path)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Unescape from host FS
|
|
|
|
|
|
std::vector<std::string> escaped = fmt::split(path, {std::string_view{&fs::delim[0], 1}, std::string_view{&fs::delim[1], 1}});
|
|
|
|
|
|
std::vector<std::string> result;
|
|
|
|
|
|
for (auto& sv : escaped)
|
|
|
|
|
|
result.emplace_back(vfs::unescape(sv));
|
|
|
|
|
|
|
|
|
|
|
|
return fmt::merge(result, "/");
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-01-13 05:24:04 +01:00
|
|
|
|
const std::string resolved_hdd0 = GetCallbacks().resolve_path(hdd0_game) + '/';
|
2021-04-06 22:16:58 +02:00
|
|
|
|
|
2018-03-11 12:42:57 +01:00
|
|
|
|
if (from_hdd0_game && m_cat == "DG")
|
|
|
|
|
|
{
|
2021-04-06 22:16:58 +02:00
|
|
|
|
argv[0] = "/dev_bdvd/PS3_GAME/" + unescape(resolved_path.substr(resolved_hdd0.size() + 10));
|
|
|
|
|
|
m_dir = "/dev_hdd0/game/" + resolved_path.substr(resolved_hdd0.size(), 10);
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Disc path: %s", m_dir);
|
2018-03-11 12:42:57 +01:00
|
|
|
|
}
|
|
|
|
|
|
else if (from_hdd0_game)
|
2017-07-12 13:07:38 +02:00
|
|
|
|
{
|
2021-04-06 22:16:58 +02:00
|
|
|
|
argv[0] = "/dev_hdd0/game/" + unescape(resolved_path.substr(resolved_hdd0.size()));
|
|
|
|
|
|
m_dir = "/dev_hdd0/game/" + resolved_path.substr(resolved_hdd0.size(), 10);
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Boot path: %s", m_dir);
|
2017-07-12 13:07:38 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
|
2017-06-10 21:50:10 +02:00
|
|
|
|
{
|
2017-09-18 18:16:36 +02:00
|
|
|
|
// Disc games are on /dev_bdvd/
|
2021-04-06 22:16:58 +02:00
|
|
|
|
const usz pos = resolved_path.rfind(m_game_dir);
|
2021-10-15 19:59:55 +02:00
|
|
|
|
argv[0] = "/dev_bdvd/PS3_GAME/" + unescape(resolved_path.substr(pos + m_game_dir.size() + 1));
|
2018-03-11 00:35:41 +01:00
|
|
|
|
m_dir = "/dev_bdvd/PS3_GAME/";
|
2017-06-10 21:50:10 +02:00
|
|
|
|
}
|
2021-04-06 22:16:58 +02:00
|
|
|
|
else if (from_dev_flash)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Firmware executables
|
2022-01-13 05:24:04 +01:00
|
|
|
|
argv[0] = "/dev_flash" + resolved_path.substr(GetCallbacks().resolve_path(g_cfg_vfs.get_dev_flash()).size());
|
2021-04-06 22:16:58 +02:00
|
|
|
|
m_dir = fs::get_parent_dir(argv[0]) + '/';
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (g_cfg.vfs.host_root)
|
2017-06-10 21:50:10 +02:00
|
|
|
|
{
|
2017-09-18 18:16:36 +02:00
|
|
|
|
// For homebrew
|
2021-04-06 22:16:58 +02:00
|
|
|
|
argv[0] = "/host_root/" + resolved_path;
|
2018-03-11 00:35:41 +01:00
|
|
|
|
m_dir = "/host_root/" + elf_dir + '/';
|
2017-06-10 21:50:10 +02:00
|
|
|
|
}
|
2021-04-06 22:16:58 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Use /app_home if /host_root is disabled
|
|
|
|
|
|
argv[0] = "/app_home/" + resolved_path.substr(resolved_path.find_last_of(fs::delim) + 1);
|
|
|
|
|
|
m_dir = "/app_home/";
|
|
|
|
|
|
}
|
2017-06-10 21:50:10 +02:00
|
|
|
|
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.notice("Elf path: %s", argv[0]);
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2021-04-24 13:29:43 +02:00
|
|
|
|
|
2021-04-08 20:02:48 +02:00
|
|
|
|
if (!argv[0].starts_with("/dev_hdd0/game"sv) && m_cat == "HG"sv)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Booting HG category outside of HDD0!");
|
|
|
|
|
|
}
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
2021-01-12 11:01:06 +01:00
|
|
|
|
g_fxo->init<ppu_module>();
|
2016-04-14 00:59:00 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (ppu_load_exec(ppu_exec, DeserialManager()))
|
2021-01-30 15:25:21 +01:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
// Overlay (OVL) executable (only load it)
|
|
|
|
|
|
else if (vm::map(0x3000'0000, 0x1000'0000, 0x200); !ppu_load_overlay(ppu_exec, m_path).first)
|
|
|
|
|
|
{
|
2021-02-12 12:40:55 +01:00
|
|
|
|
ppu_exec.set_error(elf_error::header_type);
|
2021-01-30 15:25:21 +01:00
|
|
|
|
}
|
2021-09-07 20:09:14 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// Preserve emulation state for OVL excutable
|
|
|
|
|
|
Pause(true);
|
|
|
|
|
|
}
|
2019-01-13 18:06:30 +01:00
|
|
|
|
|
2021-01-30 15:25:21 +01:00
|
|
|
|
if (ppu_exec != elf_error::ok)
|
|
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
Kill(false);
|
2021-01-30 15:25:21 +01:00
|
|
|
|
|
|
|
|
|
|
sys_log.error("Invalid or unsupported PPU executable format: %s", elf_path);
|
|
|
|
|
|
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (ppu_prx.open(elf_file) == elf_error::ok)
|
|
|
|
|
|
{
|
2022-04-27 18:46:09 +02:00
|
|
|
|
// PPU PRX
|
RPCS3 QT (#2645)
* Fix windows build. I made sure to do everything with a win32 prefix to not effect linux build.
* Make the window resizable instead of fixed in the corner.
* Ignore moc files and things in the debug/release folder. I might also ignore rpcs3qt.vcxproj and its filters as they're autogenerated by importing the qt project file. But, this helps clean out clutter for now.
* Add cmake. This doesn't interact with the rest of rpcs3 nor the main cmake file. That's the next thing I'm doing. I'll probably need to modify them so it'll take me time to figure out. But, this will build rpcs3qt on linux and build as is with using qt.
* The build works. I'd like to thank my friends, Google and Stackoverflow.
Setted up by importing rpcs3Qt project using Qt's visual studio plugin.
* Cleanup. Remove all the stuff in the rpcs3qt folder as its incorporated elsewhere. Remove the rpcs3qt project file as its now built into the solution and cmake doesn't care about pro files.
* Update readme to reflect getting Qt.
* Remove wxwidgets as submodule and add zlib instead. Wxwidgets was our old way of having zlib. I also added build dependencies to rpcs3qt so you should no longer get link errors on the first clean rebuild.
* Add rpcs3_version, few GUI tweaks
* Set defaultSize to 70% of screen size
* Add the view menu (#3)
* Added the view menu with the corresponding elements. Now, the debugger/log are hidden by default. The view menu has a checkbox which you click to show/hide the dock widgets.
* Make log visible by default
* Improve UI by making it into a checkbox that's easier to use.
* fix qt build for vs2017 (seems to work fine in 2015 with plugin but needs testing by other users)
* updated readme for qt
* update appveyor for qt
- cleaned formatting for the post build command
* fix build (#6)
* fix build legit this time i promise
* [Ready] Gamepadsettings (#4)
* WIP Gamepadsettings
pushbutton Eventhandling missing
* GamepadSettings should work except for cfg Init
Some KeyInputs are missing
* Update padsettingsdialog.h
* Update padsettingsdialog.cpp (#5)
* Update padsettingsdialog.cpp
removed silly tabs
* Update padsettingsdialog.cpp
* GetKeyCode simplified
* rename pad settings to keyboard settings o.O
* rename keyboard setting to input settings
* Remvoed the QT_UI defines.
* Readded new line at end of file. Replaced define in padsettings with constant.
* GUI fixes (Settings)
* Stub the logger UI. Nothing special besides a simple stub.
* Unstub the log. I haven't tested TTY but it should work.
Only thing to do, but this is in general, is add persistent settings.
* Minor refactoring to simplify code.
* Fix image loading. I'm 90% sure it works because it loads the path as expected and that's the same format I used in my gamelist implementation for the images.
* Made game lists much more functional than it was.
* mainwindow
* gamelist
* Please forgive me for I have lambdaed.
Added the ability to toggle showing columns via a context menu.
* Fix GameList further
* sort by name on init fixed
* Created the baseline refactoring. I'm going to start working on the callbacks now. May need to implement other classes in the process. Fun stuff, I know.
* adds InstallPkg (tested) and InstallPup (should work but makes unknown shenanigans) implementation
adds RefreshGameList
obliterates 10sec Refresh
* messages
* Rpcs3 gs frame (#16)
* Messing with project settings try to get trails of cold steel to boot.bluh
Definitely one change is needed in linker settings for RPCS3 to not crash immediately.
Can't even see how horribly botched my implementation of GSFrame is because we aren't booting lol. Something is gone awry with elf.
* remove random ! not that it matters much right now
* minor additions
* "Working" with debug mode though you have to ignore an assert reached from Qt. Qt is upset that the rsx thread is calling stuff on the UI thread despite not owning it. However, I can't do a thing to change that atm. (The fix would be to do what the TODO says in System.cpp-- making gsframe and stuff get initialized via system call)
Crashes due to needing pad callback to be done.
* With this build in debug mode, Trails of Cold steel will get FPS. (caveat. You have to ignore when Qt throws a debug assert lol)
* Fix release mode. Fix the Qt debug assert by using ancient occault rituals. I want to be able to remove the blocking connects but it won't work right now without it. It isn't perfect but it's good enough for now IMO.
* Add enters to the end of files.
* Removing target and setting source of events to be the application instead of the main window. The main window isn't the game window, and I don't really know what widget will be targetted for the game event. Works, though, it's admittedly probably not optimal by ANY means.
* Fix comment.
* Fix libpng wit zlib.
* Move Qt GUI into RPCS3Qt. (#17)
Restore wx GUI.
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* Add stylesheet to git ignore.
* XInput..
* Joystick...
* Rpcs3 qt small fixes (#20)
* Small fixes. Have emulator stop when x button is pressed on game window. Have emulator/application stop when the main window is closed.
* If I forget another new line ending for a file.............................................
* Add CgDisasm (#21)
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* add CgDisasm
add code to disable contextmenu options
fix gamelist issue
* missing proj changes
* Add ability to open stylesheets from menu.
* Mega searcher (#23)
* add MemoryStringSearcher
set minimum Sizes for mainwindow and CgDisasm
* minor fixes
* Since the system.cpp callbacks for emulator state were unused, I removed them. Then, I replaced them with callbacks for the Gui.
* added stylesheet options
setfocus on settings fixed
newline added
* added signals and slots for EmuRun and EmuStop
* update ui
update ui now works
added callback onReady
added EnableMenues
added ps3 commands
* added restart logic to menu
* newline
* event header removed
* Added graphic settings class. (#26)
* Added graphic settings class. First thing is to have the dock widgets and window size/location be stateful. Minor bug with debugger frame changing size on hide/show on default setup on second load. But, otherwise, fine. Also, the GUI doesn't update to accomodate the statefulness of the widgets. But, that'll come in time as I update this class.
* Add view debugger, logger, gamelist to settings and synchronize them.
* Separate initializing actions from connects
* Add invisible fullscreen cursor and double click event.
* Add the UI log settings.
* Add MemoryViewer (#30)
* Add Memoryviewer
Image Button crashes/not fully implemented
focus on some button annoying
minor changes for question dialogs
* GuiSettings Refactoring (#31)
* Add settings for columns shown and which one is saved
* I accidentally refactored the settings class. Added ability to reset to default GUI. Added statefulness to column widths.
* add gui tab
* Fix logging at startup.
* Preset settings.I think I ironed out MOST of the glitches. Will work on the rest of it soon. Should be a lot simpler as I won't have to use the so-called meta settings. Also, renamed all settings methods to CapitalCase.
* Removed dock widget controls.
* Added style sheets. Removed the option from the menu.
* Rewrite to use folder design. Much simpler! Yay! Simpler. Better, right?
* It's remarkable how tricky this is.
* Added convenience button to open up the settings folder in explorer
* Add newlines at end of file
* simplified logic. Fixed a bug.. hopefully not more bugs
* Fix the undocumented feature
* Make the dialog big enough to have entire text on title shown. If talkashie changes the font to size 1203482 I don't care lol
* Make warning messagebox instead of changing the title of the dialog.
* marking...
* Hcorion suggested changes.
* [WIP] autopause (#32)
* autopause added
needs fixing
headers do not show text
* fix compile stuff
* Add MsgDialog + edge widgets (#33)
* Add MsgDialog
needs magic
* add "Debugger" Buttons to menubar
* Adapt ds4 changes. I'm not sure if they work as I don't have a compatible controller. But, at the same time, it's kind of silly all I had to do was remove stdguiafx to get compilation.
* [Ready] Add KernelExplorer (#36)
* KernelExplorer added
* Fix build. Connect mainwindow to show explorer.
* qstr formatting added
hid header, fixed button size
* Taskbar Progress for install PUP/PKG (#37)
* Add Taskbar Progress for both PKG and PUP installer
* fix missing ifdefs for windows
* add mainwindow icon + thumbnail toolbar
* add game specific icons to the GSFrame
* fix icon crash
* fix appIcon's aspect ratio in SetAppIconFromPath
* Fix black borders in RGB32 icons
* rename thumbar related buttons
* EmuSettings (#35)
* Core tab done minus doing the library list.
* Graphics tab.
* Audio tab
* Input tab
* Added the other tabs
* LLE part one-- load existing libraries sorted. (I'd finish it but I'm going to look at a PR by mega)
* add search and add other libraries that aren't checked.
* Finish adding lle selecting things.
* marking my territory (#38)
fixed settingsdialog glitch and width
added groupbox to gui buttons
removed parents from layouts
* add debuggerframe + RSXDebugger (#34)
* Add Debuggerframe
* add RSXDebugger
* add RSXDebugger fo real
* RSXDebugger improved
minor adjustments
* add utf8 conversions like neko told me to
hopefully i did not utf8-ise too many things xD
* fix some variables
* maybe fix image buffers in RSXDebugger
* fixed image view (pretty sure)
* fixed image buffer (hopefully)
* QT Opengl frame (#41)
* fix RSX Debugger headers (#40)
* fix some debugger layout issues
fix RSX Debugger headers + some comments
* add kd-11's SPU options
fix D3D12 showing on non-compatible systems
tidy up coretab
* improve D3D12 behaviour in graphicstab:
adapter selection and D3D12 render won't show on non-compatible systems
add monospace font to cgDisasm
* enable update only on visibility
* Rpcs3 qt llvm build (#42)
* LLVM pushed so mega can test
* probably is what is needed with Release LLVM
* should probably have RPCS3-Qt be using release-llvm
* include zlib the same way.
* don't talk to me about how I made this happen.
* I applied the magical treatment to debug mode too. Though, it's entirely probably that doing it once in LLVM-release mode made this entirely redundant
* hack
* progress bar for LLVM spawns but doesn't close yet.
* fix msgDialog (#43)
fix oskDialog
* Minor bug fixzz
* fix osk and msgdialog for real (#44)
* fix msgDialog
fix oskDialog
* fix OskDialog part 2
fix MsgDialog part 2
* This bug is evil, and it should be ashamed of itself.
* Refactor YAML. Commented out gui options that aren't added to config yet (add em back later when we merge that in)
* Fix pad stuff.
* add SaveDataUtility (#45)
* add SaveDataUtility
* fix slots
* fix slots again
fix lists not showing stuff
fix dialogs not showing
add colClicked
refactor stuff and polish some layouts
* add SaveDataDialog.h and SaveDataDialog.cpp
* tidy up mainwindow
* add callback
* fix RegisterEditor (#47)
* fix RegisterEditor
* fix other dialogs' immortality (gasp...vampires)
* remove debug leftovers
* fix InstructionEditor (#46)
* fix InstructionEditor
* fix typo
* Fix MouseClickEvents in RSXDebugger (#50)
* Fix MouseClickEvents in RSXDebugger
Fix focus on MemoryViewer and RSXDebugger
Adjust PadButtonWidth
* fix another comment
* fix debuggerframe events (#49)
* Fix pad settings bro (#48)
* Fix pad settings bro
* fix comment
* Icons and Menu-Additions (#39)
* Add Icons and iconlogic to cornerWidget and actions
* add cornerWidget toggle
fix dockwidget action state on start
remove DoSettings
* fix game removal bug
remove tableitem focus rectangle
therefore add TableItemDelegate.h
* remove grid and focus rectangle from autopausedialog
* add fullscreen checkbox to misctab
minor padsettings layout improvements
* Add show category submenu to view menu
Add gamelist filter accordingly
fix minor bug where play icon was displayed despite pause label
add boolean b_fullscreen to mainwindow for later use in GSFrame
* fix headers in autopausesettings
fix remove bug in autopausesettings
add delete keypressevent in autopausesettings
fix missing tr() and minor refactoring in gamelist
* add default Icons for play/pause/stop/restart
* Fix fullscreen start. Some stuff was wrong with settings, just trust me.
* remove fullscreen leftovers and fix merge
* SPU stuff. (There was also a weird thing with config.h in GLGSFrame.h with an include that I removed to fix build)
* please neko's lambda fetishes (#53)
* please neko's lambda fetish in mainwindow
* please neko's lambda fetish in gamelistframe
* please neko's lambda fetish in logframe
* fix neko's lambda fetish in debuggerframe
* pleasefixdofetishsomething in Autopausesettingsdialog
* fix sth sth lambda in cg disasm
* lambda stuff in instructioneditor
* lambda kernelexplorer
* lambda-ise memoryviewer
* lambda rsxdebugger
* lambda savedatautil
this could be done even more, but the functions are not implemented
* Rpcs3 qt fixes -- shadow taskbar bug (#52)
* SShadow's bug of taskbar progress staying fixed on cancelling pkg install.
* other taskbar
* i'm still a baka
* Fix a warning
* qtQt refactoring (#54)
* fix neko's snake fetish
* File names should match headers. Are these the names I want? Not necessarily. But, this is much less confusing.
* i thought I committed everything with stage all.........................
* remove unused utilities
* The most important commit of them all.
* Disable legacy opengl buffers when not using opengl.
* fix code review comment
* Quick crash patch. Neko removed autopause. SO, I remove it too from emusettings/misc tab
* Merge lovely things from master (#55)
* Configuration simplified
* untrivial parts of the merge
* no need for these options anymore
* Minor change to fix column widths at startup (not sure why it doesn't work already, but adding the true makes it work so......... whatever)
* here ya go
* FIx hitting okay in settings causing graphics to messup (#57)
* fixes + msgdialog taskbarprogress (#56)
* fix ok button in taskbar
add taskicon progressbar for msgdialog
add tablewidgetitem to rsxdebugger
fix comments in save_data_utility.cpp
* fix d3d adapter default
* fix taskicon progressbar not being destroyed properly
* add last_path to filedialogs
* fix msgdialog crash on ok (#58)
* fix thread stopping in debbugerFrame (#59)
* Move Emu.init to be first. This will fix the qt stuff seeming to ignore the virtual filesystem in the config. (VFS to be made soon maybe) (#60)
* Fix full screen opening on double RIGHT click.
* fix other instances of double click ...
* Fix locaiton of gui config. (#61)
* fix d3d bug (#62)
* fix d3d bug
* small utf8 addition
* Fix cmake for qt (#64)
* Initial CMake fix
* Fix compilation with GCC
* Get rid of awful hack
* Update cotire with qt support
* Maybe fix travis
* Emergency Hack Relief Program Activated
* Fix travis build (#65)
* make about dialog great again (#67)
and add previous additions
* Fix library sort / smart gamelist context menu (#63)
* fix library sort
* add Title to custom game config dialog
* disable options on gamelist context menu
* use namespace for category Strings
* introduce sstr
* fix some tr nonsense
* Rpcs3qt Appveyor (#68)
Fix appyveyor build!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* possible fix for gamelist icons (#69)
add warning for appicon
* Fix clang build (#66)
Hcorion, the build savior.
* Rpcs3 qt resources (#70)
* Resource files attempt 1
* Autorcc should probably be on?
* forgot the most important file lol
* Forgot an instance of the icon in the code...
* Patch fix for clang build.
* vulkan/d3d12 combobox merge (#71)
* add vulkan adapterbox and merge with d3d12 box
* fix adapter text on other renderer
* gather render strings
* attempt fix on gamelist row height
* adjust adapter behaviour to new guideline
* Compiler of Peace.
* High critical hit rate.
* Mugi eating strawberries is savage.
* Apply KD-11 Hotfix (#73)
* Most of Ani Adjusts (#72)
* Most of the adjustments are made here.
* fix gamelist rowheight
* fix msg dialog layout and disable_cancel
* cleanup
* fix disable cancle again
* fix debuggerframe buttons and doubleclick
* Add a fun little bonus feature :) (#74)
* category filters simplyfied (#75)
* Cleaning up cmake a bit.
* fixezzzzzz (#76)
* upgrade Info Boxes
* upgrade file explorer
* refactor GetSettings and SetSettings
* second refactoring
* cleanup
* travis is a grammar nazi
* second travis shenanigans
* third travis weirdo thingy
* travis 4 mega fun
* travis 5 default to def
* finish refactoring for settings
fix gamelist headers
* hotfix msgdialog and infobox (#77)
* msgdialog fix 1
* fix zombie infobox
* Rpcs3 Qt Welcome Page (#78)
* Add a welcome dialog.
* Add enter to end of file
* i'm an idiot
* last mistake i hope
* sponsored via --> funded by
* RPCS3 does not condone piracy.
* Mega Adjusts
* Ani Adjustments and a few refactorings
* Yay
* Add Gamelist Icon Sizes (#79)
* Reverting Mega's suggestion. If people can use alt-f4 to get around this dialog, they can probably use an emulator too.
* Fix firmware file choice dialog in QT GUI (#80)
* ani adjusts 2 + minor icon size simplifications (#81)
FPS Additions
* Update Travis to Qt 5.9 (#82)
2017-06-04 16:48:33 +02:00
|
|
|
|
GetCallbacks().on_ready();
|
2021-02-03 19:14:31 +01:00
|
|
|
|
g_fxo->init(false);
|
2017-07-13 17:35:37 +02:00
|
|
|
|
ppu_load_prx(ppu_prx, m_path);
|
2021-09-07 20:09:14 +02:00
|
|
|
|
Pause(true);
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
else if (spu_exec.open(elf_file) == elf_error::ok)
|
|
|
|
|
|
{
|
2022-04-27 18:46:09 +02:00
|
|
|
|
// SPU executable
|
RPCS3 QT (#2645)
* Fix windows build. I made sure to do everything with a win32 prefix to not effect linux build.
* Make the window resizable instead of fixed in the corner.
* Ignore moc files and things in the debug/release folder. I might also ignore rpcs3qt.vcxproj and its filters as they're autogenerated by importing the qt project file. But, this helps clean out clutter for now.
* Add cmake. This doesn't interact with the rest of rpcs3 nor the main cmake file. That's the next thing I'm doing. I'll probably need to modify them so it'll take me time to figure out. But, this will build rpcs3qt on linux and build as is with using qt.
* The build works. I'd like to thank my friends, Google and Stackoverflow.
Setted up by importing rpcs3Qt project using Qt's visual studio plugin.
* Cleanup. Remove all the stuff in the rpcs3qt folder as its incorporated elsewhere. Remove the rpcs3qt project file as its now built into the solution and cmake doesn't care about pro files.
* Update readme to reflect getting Qt.
* Remove wxwidgets as submodule and add zlib instead. Wxwidgets was our old way of having zlib. I also added build dependencies to rpcs3qt so you should no longer get link errors on the first clean rebuild.
* Add rpcs3_version, few GUI tweaks
* Set defaultSize to 70% of screen size
* Add the view menu (#3)
* Added the view menu with the corresponding elements. Now, the debugger/log are hidden by default. The view menu has a checkbox which you click to show/hide the dock widgets.
* Make log visible by default
* Improve UI by making it into a checkbox that's easier to use.
* fix qt build for vs2017 (seems to work fine in 2015 with plugin but needs testing by other users)
* updated readme for qt
* update appveyor for qt
- cleaned formatting for the post build command
* fix build (#6)
* fix build legit this time i promise
* [Ready] Gamepadsettings (#4)
* WIP Gamepadsettings
pushbutton Eventhandling missing
* GamepadSettings should work except for cfg Init
Some KeyInputs are missing
* Update padsettingsdialog.h
* Update padsettingsdialog.cpp (#5)
* Update padsettingsdialog.cpp
removed silly tabs
* Update padsettingsdialog.cpp
* GetKeyCode simplified
* rename pad settings to keyboard settings o.O
* rename keyboard setting to input settings
* Remvoed the QT_UI defines.
* Readded new line at end of file. Replaced define in padsettings with constant.
* GUI fixes (Settings)
* Stub the logger UI. Nothing special besides a simple stub.
* Unstub the log. I haven't tested TTY but it should work.
Only thing to do, but this is in general, is add persistent settings.
* Minor refactoring to simplify code.
* Fix image loading. I'm 90% sure it works because it loads the path as expected and that's the same format I used in my gamelist implementation for the images.
* Made game lists much more functional than it was.
* mainwindow
* gamelist
* Please forgive me for I have lambdaed.
Added the ability to toggle showing columns via a context menu.
* Fix GameList further
* sort by name on init fixed
* Created the baseline refactoring. I'm going to start working on the callbacks now. May need to implement other classes in the process. Fun stuff, I know.
* adds InstallPkg (tested) and InstallPup (should work but makes unknown shenanigans) implementation
adds RefreshGameList
obliterates 10sec Refresh
* messages
* Rpcs3 gs frame (#16)
* Messing with project settings try to get trails of cold steel to boot.bluh
Definitely one change is needed in linker settings for RPCS3 to not crash immediately.
Can't even see how horribly botched my implementation of GSFrame is because we aren't booting lol. Something is gone awry with elf.
* remove random ! not that it matters much right now
* minor additions
* "Working" with debug mode though you have to ignore an assert reached from Qt. Qt is upset that the rsx thread is calling stuff on the UI thread despite not owning it. However, I can't do a thing to change that atm. (The fix would be to do what the TODO says in System.cpp-- making gsframe and stuff get initialized via system call)
Crashes due to needing pad callback to be done.
* With this build in debug mode, Trails of Cold steel will get FPS. (caveat. You have to ignore when Qt throws a debug assert lol)
* Fix release mode. Fix the Qt debug assert by using ancient occault rituals. I want to be able to remove the blocking connects but it won't work right now without it. It isn't perfect but it's good enough for now IMO.
* Add enters to the end of files.
* Removing target and setting source of events to be the application instead of the main window. The main window isn't the game window, and I don't really know what widget will be targetted for the game event. Works, though, it's admittedly probably not optimal by ANY means.
* Fix comment.
* Fix libpng wit zlib.
* Move Qt GUI into RPCS3Qt. (#17)
Restore wx GUI.
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* Add stylesheet to git ignore.
* XInput..
* Joystick...
* Rpcs3 qt small fixes (#20)
* Small fixes. Have emulator stop when x button is pressed on game window. Have emulator/application stop when the main window is closed.
* If I forget another new line ending for a file.............................................
* Add CgDisasm (#21)
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* add CgDisasm
add code to disable contextmenu options
fix gamelist issue
* missing proj changes
* Add ability to open stylesheets from menu.
* Mega searcher (#23)
* add MemoryStringSearcher
set minimum Sizes for mainwindow and CgDisasm
* minor fixes
* Since the system.cpp callbacks for emulator state were unused, I removed them. Then, I replaced them with callbacks for the Gui.
* added stylesheet options
setfocus on settings fixed
newline added
* added signals and slots for EmuRun and EmuStop
* update ui
update ui now works
added callback onReady
added EnableMenues
added ps3 commands
* added restart logic to menu
* newline
* event header removed
* Added graphic settings class. (#26)
* Added graphic settings class. First thing is to have the dock widgets and window size/location be stateful. Minor bug with debugger frame changing size on hide/show on default setup on second load. But, otherwise, fine. Also, the GUI doesn't update to accomodate the statefulness of the widgets. But, that'll come in time as I update this class.
* Add view debugger, logger, gamelist to settings and synchronize them.
* Separate initializing actions from connects
* Add invisible fullscreen cursor and double click event.
* Add the UI log settings.
* Add MemoryViewer (#30)
* Add Memoryviewer
Image Button crashes/not fully implemented
focus on some button annoying
minor changes for question dialogs
* GuiSettings Refactoring (#31)
* Add settings for columns shown and which one is saved
* I accidentally refactored the settings class. Added ability to reset to default GUI. Added statefulness to column widths.
* add gui tab
* Fix logging at startup.
* Preset settings.I think I ironed out MOST of the glitches. Will work on the rest of it soon. Should be a lot simpler as I won't have to use the so-called meta settings. Also, renamed all settings methods to CapitalCase.
* Removed dock widget controls.
* Added style sheets. Removed the option from the menu.
* Rewrite to use folder design. Much simpler! Yay! Simpler. Better, right?
* It's remarkable how tricky this is.
* Added convenience button to open up the settings folder in explorer
* Add newlines at end of file
* simplified logic. Fixed a bug.. hopefully not more bugs
* Fix the undocumented feature
* Make the dialog big enough to have entire text on title shown. If talkashie changes the font to size 1203482 I don't care lol
* Make warning messagebox instead of changing the title of the dialog.
* marking...
* Hcorion suggested changes.
* [WIP] autopause (#32)
* autopause added
needs fixing
headers do not show text
* fix compile stuff
* Add MsgDialog + edge widgets (#33)
* Add MsgDialog
needs magic
* add "Debugger" Buttons to menubar
* Adapt ds4 changes. I'm not sure if they work as I don't have a compatible controller. But, at the same time, it's kind of silly all I had to do was remove stdguiafx to get compilation.
* [Ready] Add KernelExplorer (#36)
* KernelExplorer added
* Fix build. Connect mainwindow to show explorer.
* qstr formatting added
hid header, fixed button size
* Taskbar Progress for install PUP/PKG (#37)
* Add Taskbar Progress for both PKG and PUP installer
* fix missing ifdefs for windows
* add mainwindow icon + thumbnail toolbar
* add game specific icons to the GSFrame
* fix icon crash
* fix appIcon's aspect ratio in SetAppIconFromPath
* Fix black borders in RGB32 icons
* rename thumbar related buttons
* EmuSettings (#35)
* Core tab done minus doing the library list.
* Graphics tab.
* Audio tab
* Input tab
* Added the other tabs
* LLE part one-- load existing libraries sorted. (I'd finish it but I'm going to look at a PR by mega)
* add search and add other libraries that aren't checked.
* Finish adding lle selecting things.
* marking my territory (#38)
fixed settingsdialog glitch and width
added groupbox to gui buttons
removed parents from layouts
* add debuggerframe + RSXDebugger (#34)
* Add Debuggerframe
* add RSXDebugger
* add RSXDebugger fo real
* RSXDebugger improved
minor adjustments
* add utf8 conversions like neko told me to
hopefully i did not utf8-ise too many things xD
* fix some variables
* maybe fix image buffers in RSXDebugger
* fixed image view (pretty sure)
* fixed image buffer (hopefully)
* QT Opengl frame (#41)
* fix RSX Debugger headers (#40)
* fix some debugger layout issues
fix RSX Debugger headers + some comments
* add kd-11's SPU options
fix D3D12 showing on non-compatible systems
tidy up coretab
* improve D3D12 behaviour in graphicstab:
adapter selection and D3D12 render won't show on non-compatible systems
add monospace font to cgDisasm
* enable update only on visibility
* Rpcs3 qt llvm build (#42)
* LLVM pushed so mega can test
* probably is what is needed with Release LLVM
* should probably have RPCS3-Qt be using release-llvm
* include zlib the same way.
* don't talk to me about how I made this happen.
* I applied the magical treatment to debug mode too. Though, it's entirely probably that doing it once in LLVM-release mode made this entirely redundant
* hack
* progress bar for LLVM spawns but doesn't close yet.
* fix msgDialog (#43)
fix oskDialog
* Minor bug fixzz
* fix osk and msgdialog for real (#44)
* fix msgDialog
fix oskDialog
* fix OskDialog part 2
fix MsgDialog part 2
* This bug is evil, and it should be ashamed of itself.
* Refactor YAML. Commented out gui options that aren't added to config yet (add em back later when we merge that in)
* Fix pad stuff.
* add SaveDataUtility (#45)
* add SaveDataUtility
* fix slots
* fix slots again
fix lists not showing stuff
fix dialogs not showing
add colClicked
refactor stuff and polish some layouts
* add SaveDataDialog.h and SaveDataDialog.cpp
* tidy up mainwindow
* add callback
* fix RegisterEditor (#47)
* fix RegisterEditor
* fix other dialogs' immortality (gasp...vampires)
* remove debug leftovers
* fix InstructionEditor (#46)
* fix InstructionEditor
* fix typo
* Fix MouseClickEvents in RSXDebugger (#50)
* Fix MouseClickEvents in RSXDebugger
Fix focus on MemoryViewer and RSXDebugger
Adjust PadButtonWidth
* fix another comment
* fix debuggerframe events (#49)
* Fix pad settings bro (#48)
* Fix pad settings bro
* fix comment
* Icons and Menu-Additions (#39)
* Add Icons and iconlogic to cornerWidget and actions
* add cornerWidget toggle
fix dockwidget action state on start
remove DoSettings
* fix game removal bug
remove tableitem focus rectangle
therefore add TableItemDelegate.h
* remove grid and focus rectangle from autopausedialog
* add fullscreen checkbox to misctab
minor padsettings layout improvements
* Add show category submenu to view menu
Add gamelist filter accordingly
fix minor bug where play icon was displayed despite pause label
add boolean b_fullscreen to mainwindow for later use in GSFrame
* fix headers in autopausesettings
fix remove bug in autopausesettings
add delete keypressevent in autopausesettings
fix missing tr() and minor refactoring in gamelist
* add default Icons for play/pause/stop/restart
* Fix fullscreen start. Some stuff was wrong with settings, just trust me.
* remove fullscreen leftovers and fix merge
* SPU stuff. (There was also a weird thing with config.h in GLGSFrame.h with an include that I removed to fix build)
* please neko's lambda fetishes (#53)
* please neko's lambda fetish in mainwindow
* please neko's lambda fetish in gamelistframe
* please neko's lambda fetish in logframe
* fix neko's lambda fetish in debuggerframe
* pleasefixdofetishsomething in Autopausesettingsdialog
* fix sth sth lambda in cg disasm
* lambda stuff in instructioneditor
* lambda kernelexplorer
* lambda-ise memoryviewer
* lambda rsxdebugger
* lambda savedatautil
this could be done even more, but the functions are not implemented
* Rpcs3 qt fixes -- shadow taskbar bug (#52)
* SShadow's bug of taskbar progress staying fixed on cancelling pkg install.
* other taskbar
* i'm still a baka
* Fix a warning
* qtQt refactoring (#54)
* fix neko's snake fetish
* File names should match headers. Are these the names I want? Not necessarily. But, this is much less confusing.
* i thought I committed everything with stage all.........................
* remove unused utilities
* The most important commit of them all.
* Disable legacy opengl buffers when not using opengl.
* fix code review comment
* Quick crash patch. Neko removed autopause. SO, I remove it too from emusettings/misc tab
* Merge lovely things from master (#55)
* Configuration simplified
* untrivial parts of the merge
* no need for these options anymore
* Minor change to fix column widths at startup (not sure why it doesn't work already, but adding the true makes it work so......... whatever)
* here ya go
* FIx hitting okay in settings causing graphics to messup (#57)
* fixes + msgdialog taskbarprogress (#56)
* fix ok button in taskbar
add taskicon progressbar for msgdialog
add tablewidgetitem to rsxdebugger
fix comments in save_data_utility.cpp
* fix d3d adapter default
* fix taskicon progressbar not being destroyed properly
* add last_path to filedialogs
* fix msgdialog crash on ok (#58)
* fix thread stopping in debbugerFrame (#59)
* Move Emu.init to be first. This will fix the qt stuff seeming to ignore the virtual filesystem in the config. (VFS to be made soon maybe) (#60)
* Fix full screen opening on double RIGHT click.
* fix other instances of double click ...
* Fix locaiton of gui config. (#61)
* fix d3d bug (#62)
* fix d3d bug
* small utf8 addition
* Fix cmake for qt (#64)
* Initial CMake fix
* Fix compilation with GCC
* Get rid of awful hack
* Update cotire with qt support
* Maybe fix travis
* Emergency Hack Relief Program Activated
* Fix travis build (#65)
* make about dialog great again (#67)
and add previous additions
* Fix library sort / smart gamelist context menu (#63)
* fix library sort
* add Title to custom game config dialog
* disable options on gamelist context menu
* use namespace for category Strings
* introduce sstr
* fix some tr nonsense
* Rpcs3qt Appveyor (#68)
Fix appyveyor build!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* possible fix for gamelist icons (#69)
add warning for appicon
* Fix clang build (#66)
Hcorion, the build savior.
* Rpcs3 qt resources (#70)
* Resource files attempt 1
* Autorcc should probably be on?
* forgot the most important file lol
* Forgot an instance of the icon in the code...
* Patch fix for clang build.
* vulkan/d3d12 combobox merge (#71)
* add vulkan adapterbox and merge with d3d12 box
* fix adapter text on other renderer
* gather render strings
* attempt fix on gamelist row height
* adjust adapter behaviour to new guideline
* Compiler of Peace.
* High critical hit rate.
* Mugi eating strawberries is savage.
* Apply KD-11 Hotfix (#73)
* Most of Ani Adjusts (#72)
* Most of the adjustments are made here.
* fix gamelist rowheight
* fix msg dialog layout and disable_cancel
* cleanup
* fix disable cancle again
* fix debuggerframe buttons and doubleclick
* Add a fun little bonus feature :) (#74)
* category filters simplyfied (#75)
* Cleaning up cmake a bit.
* fixezzzzzz (#76)
* upgrade Info Boxes
* upgrade file explorer
* refactor GetSettings and SetSettings
* second refactoring
* cleanup
* travis is a grammar nazi
* second travis shenanigans
* third travis weirdo thingy
* travis 4 mega fun
* travis 5 default to def
* finish refactoring for settings
fix gamelist headers
* hotfix msgdialog and infobox (#77)
* msgdialog fix 1
* fix zombie infobox
* Rpcs3 Qt Welcome Page (#78)
* Add a welcome dialog.
* Add enter to end of file
* i'm an idiot
* last mistake i hope
* sponsored via --> funded by
* RPCS3 does not condone piracy.
* Mega Adjusts
* Ani Adjustments and a few refactorings
* Yay
* Add Gamelist Icon Sizes (#79)
* Reverting Mega's suggestion. If people can use alt-f4 to get around this dialog, they can probably use an emulator too.
* Fix firmware file choice dialog in QT GUI (#80)
* ani adjusts 2 + minor icon size simplifications (#81)
FPS Additions
* Update Travis to Qt 5.9 (#82)
2017-06-04 16:48:33 +02:00
|
|
|
|
GetCallbacks().on_ready();
|
2021-02-03 19:14:31 +01:00
|
|
|
|
g_fxo->init(false);
|
2016-07-09 00:36:42 +02:00
|
|
|
|
spu_load_exec(spu_exec);
|
2021-09-07 20:09:14 +02:00
|
|
|
|
Pause(true);
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2022-04-27 18:46:09 +02:00
|
|
|
|
else if (spu_rel.open(elf_file) == elf_error::ok)
|
|
|
|
|
|
{
|
|
|
|
|
|
// SPU linker file
|
|
|
|
|
|
GetCallbacks().on_ready();
|
|
|
|
|
|
g_fxo->init(false);
|
|
|
|
|
|
spu_load_rel_exec(spu_rel);
|
|
|
|
|
|
Pause(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (ppu_rel.open(elf_file) == elf_error::ok)
|
|
|
|
|
|
{
|
|
|
|
|
|
// PPU linker file
|
|
|
|
|
|
GetCallbacks().on_ready();
|
|
|
|
|
|
g_fxo->init(false);
|
|
|
|
|
|
ppu_load_rel_exec(ppu_rel);
|
|
|
|
|
|
Pause(true);
|
|
|
|
|
|
}
|
2016-04-14 00:59:00 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.error("Invalid or unsupported file format: %s", elf_path);
|
2013-10-06 14:07:42 +02:00
|
|
|
|
|
2020-02-01 05:36:53 +01:00
|
|
|
|
sys_log.warning("** ppu_exec -> %s", ppu_exec.get_error());
|
|
|
|
|
|
sys_log.warning("** ppu_prx -> %s", ppu_prx.get_error());
|
|
|
|
|
|
sys_log.warning("** spu_exec -> %s", spu_exec.get_error());
|
2022-04-27 18:46:09 +02:00
|
|
|
|
sys_log.warning("** spu_rel -> %s", spu_rel.get_error());
|
|
|
|
|
|
sys_log.warning("** ppu_rel -> %s", ppu_rel.get_error());
|
2021-03-30 18:37:51 +02:00
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
Kill(false);
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
2016-04-14 00:59:00 +02:00
|
|
|
|
}
|
2013-09-24 23:11:29 +02:00
|
|
|
|
|
2021-09-23 20:12:06 +02:00
|
|
|
|
if (ppu_exec == elf_error::ok && !fs::is_file(g_cfg_vfs.get_dev_flash() + "sys/external/liblv2.sprx"))
|
2017-04-13 01:31:42 +02:00
|
|
|
|
{
|
2021-03-31 20:17:40 +02:00
|
|
|
|
const auto libs = g_cfg.core.libraries_control.get_set();
|
2021-01-27 17:22:06 +01:00
|
|
|
|
|
2021-03-31 20:17:40 +02:00
|
|
|
|
extern const std::map<std::string_view, int> g_prx_list;
|
2021-01-27 17:22:06 +01:00
|
|
|
|
|
2021-03-31 20:17:40 +02:00
|
|
|
|
// Check if there are any firmware SPRX which may be LLEd during emulation
|
|
|
|
|
|
// Don't prompt GUI confirmation if there aren't any
|
|
|
|
|
|
if (std::any_of(g_prx_list.begin(), g_prx_list.end(), [&libs](auto& lib)
|
|
|
|
|
|
{
|
|
|
|
|
|
return libs.count(std::string(lib.first) + ":lle") || (!lib.second && !libs.count(std::string(lib.first) + ":hle"));
|
|
|
|
|
|
}))
|
|
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
Kill(false);
|
2021-01-27 17:22:06 +01:00
|
|
|
|
|
2022-01-20 18:44:49 +01:00
|
|
|
|
CallFromMainThread([this]()
|
2021-03-31 20:17:40 +02:00
|
|
|
|
{
|
|
|
|
|
|
GetCallbacks().on_missing_fw();
|
|
|
|
|
|
});
|
2021-01-27 17:22:06 +01:00
|
|
|
|
|
2021-03-31 20:17:40 +02:00
|
|
|
|
return game_boot_result::firmware_missing;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-12-07 18:10:34 +01:00
|
|
|
|
|
2021-03-31 20:17:40 +02:00
|
|
|
|
const bool autostart = (std::exchange(m_force_boot, false) || g_cfg.misc.autostart);
|
|
|
|
|
|
|
|
|
|
|
|
if (IsReady())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (autostart)
|
|
|
|
|
|
{
|
2020-10-08 07:27:20 +02:00
|
|
|
|
Run(true);
|
|
|
|
|
|
}
|
2021-03-31 20:17:40 +02:00
|
|
|
|
}
|
2021-03-02 15:56:23 +01:00
|
|
|
|
|
2020-02-25 16:33:06 +01:00
|
|
|
|
return game_boot_result::no_errors;
|
2013-09-24 23:11:29 +02:00
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-07 21:55:29 +01:00
|
|
|
|
void Emulator::Run(bool start_playtime)
|
2013-06-30 10:46:29 +02:00
|
|
|
|
{
|
2021-03-02 15:56:23 +01:00
|
|
|
|
ensure(IsReady());
|
2014-12-28 23:53:31 +01:00
|
|
|
|
|
2020-02-07 21:55:29 +01:00
|
|
|
|
GetCallbacks().on_run(start_playtime);
|
2015-10-13 19:32:08 +02:00
|
|
|
|
|
2015-07-04 21:23:10 +02:00
|
|
|
|
m_pause_start_time = 0;
|
|
|
|
|
|
m_pause_amend_time = 0;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
2021-04-21 22:12:21 +02:00
|
|
|
|
rpcs3::utils::configure_logs();
|
2020-02-01 05:14:26 +01:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
m_state = system_state::starting;
|
|
|
|
|
|
|
|
|
|
|
|
if (g_cfg.misc.prevent_display_sleep)
|
|
|
|
|
|
{
|
|
|
|
|
|
disable_display_sleep();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Emulator::RunPPU()
|
|
|
|
|
|
{
|
|
|
|
|
|
ensure(IsStarting());
|
2021-06-12 07:53:34 +02:00
|
|
|
|
|
2022-07-12 15:04:33 +02:00
|
|
|
|
bool signalled_thread = false;
|
|
|
|
|
|
|
2020-10-08 07:27:20 +02:00
|
|
|
|
// Run main thread
|
2022-07-12 15:04:33 +02:00
|
|
|
|
idm::select<named_thread<ppu_thread>>([&](u32, named_thread<ppu_thread>& cpu)
|
2016-04-14 00:59:00 +02:00
|
|
|
|
{
|
2022-07-11 09:53:29 +02:00
|
|
|
|
if (std::exchange(cpu.stop_flag_removal_protection, false))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-13 15:50:07 +01:00
|
|
|
|
ensure(cpu.state.test_and_reset(cpu_flag::stop));
|
|
|
|
|
|
cpu.state.notify_one(cpu_flag::stop);
|
2022-07-12 15:04:33 +02:00
|
|
|
|
signalled_thread = true;
|
2020-10-08 07:27:20 +02:00
|
|
|
|
});
|
2019-10-12 14:40:47 +02:00
|
|
|
|
|
2022-07-12 15:04:33 +02:00
|
|
|
|
if (!signalled_thread)
|
|
|
|
|
|
{
|
|
|
|
|
|
FixGuestTime();
|
|
|
|
|
|
FinalizeRunRequest();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-03 19:14:31 +01:00
|
|
|
|
if (auto thr = g_fxo->try_get<named_thread<rsx::rsx_replay_thread>>())
|
2020-10-30 20:25:33 +01:00
|
|
|
|
{
|
|
|
|
|
|
thr->state -= cpu_flag::stop;
|
2021-02-13 15:50:07 +01:00
|
|
|
|
thr->state.notify_one(cpu_flag::stop);
|
2020-10-30 20:25:33 +01:00
|
|
|
|
}
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
2020-10-30 20:25:33 +01:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
void Emulator::FixGuestTime()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_ar)
|
2019-10-12 14:40:47 +02:00
|
|
|
|
{
|
2022-07-04 15:02:17 +02:00
|
|
|
|
initialize_timebased_time(m_ar->operator u64());
|
|
|
|
|
|
|
|
|
|
|
|
g_cfg.savestate.state_inspection_mode.set(m_state_inspection_savestate);
|
|
|
|
|
|
|
|
|
|
|
|
CallFromMainThread([this]
|
|
|
|
|
|
{
|
2022-07-09 15:18:48 +02:00
|
|
|
|
m_ar.reset();
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
g_tls_log_prefix = []()
|
|
|
|
|
|
{
|
|
|
|
|
|
return std::string();
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
initialize_timebased_time(0);
|
2019-10-12 14:40:47 +02:00
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
}
|
2022-07-04 15:02:17 +02:00
|
|
|
|
void Emulator::FinalizeRunRequest()
|
|
|
|
|
|
{
|
2022-07-11 09:53:29 +02:00
|
|
|
|
auto on_select = [](u32, spu_thread& spu)
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
2022-07-11 09:53:29 +02:00
|
|
|
|
if (spu.group && spu.index == spu.group->waiter_spu_index)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (std::exchange(spu.stop_flag_removal_protection, false))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ensure(spu.state.test_and_reset(cpu_flag::stop));
|
|
|
|
|
|
spu.state.notify_one(cpu_flag::stop);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
idm::select<named_thread<spu_thread>>(on_select);
|
|
|
|
|
|
|
|
|
|
|
|
lv2_obj::awake_all();
|
|
|
|
|
|
|
|
|
|
|
|
m_state.compare_and_swap_test(system_state::starting, system_state::running);
|
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
2021-09-07 18:42:08 +02:00
|
|
|
|
bool Emulator::Pause(bool freeze_emulation)
|
2012-11-15 00:39:56 +01:00
|
|
|
|
{
|
2015-07-04 21:23:10 +02:00
|
|
|
|
const u64 start = get_system_time();
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
2021-09-07 18:42:08 +02:00
|
|
|
|
const system_state pause_state = freeze_emulation ? system_state::frozen : system_state::paused;
|
|
|
|
|
|
|
2016-04-14 00:59:00 +02:00
|
|
|
|
// Try to pause
|
2021-09-07 18:42:08 +02:00
|
|
|
|
if (!m_state.compare_and_swap_test(system_state::running, pause_state))
|
2014-06-19 15:50:18 +02:00
|
|
|
|
{
|
2021-09-07 18:42:08 +02:00
|
|
|
|
if (!freeze_emulation)
|
2021-03-31 20:17:40 +02:00
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2021-09-07 18:42:08 +02:00
|
|
|
|
|
|
|
|
|
|
if (!m_state.compare_and_swap_test(system_state::ready, pause_state))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_state.compare_and_swap_test(system_state::paused, pause_state))
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-07-04 21:23:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-10-14 19:41:31 +02:00
|
|
|
|
// Signal profilers to print results (if enabled)
|
|
|
|
|
|
cpu_thread::flush_profilers();
|
|
|
|
|
|
|
RPCS3 QT (#2645)
* Fix windows build. I made sure to do everything with a win32 prefix to not effect linux build.
* Make the window resizable instead of fixed in the corner.
* Ignore moc files and things in the debug/release folder. I might also ignore rpcs3qt.vcxproj and its filters as they're autogenerated by importing the qt project file. But, this helps clean out clutter for now.
* Add cmake. This doesn't interact with the rest of rpcs3 nor the main cmake file. That's the next thing I'm doing. I'll probably need to modify them so it'll take me time to figure out. But, this will build rpcs3qt on linux and build as is with using qt.
* The build works. I'd like to thank my friends, Google and Stackoverflow.
Setted up by importing rpcs3Qt project using Qt's visual studio plugin.
* Cleanup. Remove all the stuff in the rpcs3qt folder as its incorporated elsewhere. Remove the rpcs3qt project file as its now built into the solution and cmake doesn't care about pro files.
* Update readme to reflect getting Qt.
* Remove wxwidgets as submodule and add zlib instead. Wxwidgets was our old way of having zlib. I also added build dependencies to rpcs3qt so you should no longer get link errors on the first clean rebuild.
* Add rpcs3_version, few GUI tweaks
* Set defaultSize to 70% of screen size
* Add the view menu (#3)
* Added the view menu with the corresponding elements. Now, the debugger/log are hidden by default. The view menu has a checkbox which you click to show/hide the dock widgets.
* Make log visible by default
* Improve UI by making it into a checkbox that's easier to use.
* fix qt build for vs2017 (seems to work fine in 2015 with plugin but needs testing by other users)
* updated readme for qt
* update appveyor for qt
- cleaned formatting for the post build command
* fix build (#6)
* fix build legit this time i promise
* [Ready] Gamepadsettings (#4)
* WIP Gamepadsettings
pushbutton Eventhandling missing
* GamepadSettings should work except for cfg Init
Some KeyInputs are missing
* Update padsettingsdialog.h
* Update padsettingsdialog.cpp (#5)
* Update padsettingsdialog.cpp
removed silly tabs
* Update padsettingsdialog.cpp
* GetKeyCode simplified
* rename pad settings to keyboard settings o.O
* rename keyboard setting to input settings
* Remvoed the QT_UI defines.
* Readded new line at end of file. Replaced define in padsettings with constant.
* GUI fixes (Settings)
* Stub the logger UI. Nothing special besides a simple stub.
* Unstub the log. I haven't tested TTY but it should work.
Only thing to do, but this is in general, is add persistent settings.
* Minor refactoring to simplify code.
* Fix image loading. I'm 90% sure it works because it loads the path as expected and that's the same format I used in my gamelist implementation for the images.
* Made game lists much more functional than it was.
* mainwindow
* gamelist
* Please forgive me for I have lambdaed.
Added the ability to toggle showing columns via a context menu.
* Fix GameList further
* sort by name on init fixed
* Created the baseline refactoring. I'm going to start working on the callbacks now. May need to implement other classes in the process. Fun stuff, I know.
* adds InstallPkg (tested) and InstallPup (should work but makes unknown shenanigans) implementation
adds RefreshGameList
obliterates 10sec Refresh
* messages
* Rpcs3 gs frame (#16)
* Messing with project settings try to get trails of cold steel to boot.bluh
Definitely one change is needed in linker settings for RPCS3 to not crash immediately.
Can't even see how horribly botched my implementation of GSFrame is because we aren't booting lol. Something is gone awry with elf.
* remove random ! not that it matters much right now
* minor additions
* "Working" with debug mode though you have to ignore an assert reached from Qt. Qt is upset that the rsx thread is calling stuff on the UI thread despite not owning it. However, I can't do a thing to change that atm. (The fix would be to do what the TODO says in System.cpp-- making gsframe and stuff get initialized via system call)
Crashes due to needing pad callback to be done.
* With this build in debug mode, Trails of Cold steel will get FPS. (caveat. You have to ignore when Qt throws a debug assert lol)
* Fix release mode. Fix the Qt debug assert by using ancient occault rituals. I want to be able to remove the blocking connects but it won't work right now without it. It isn't perfect but it's good enough for now IMO.
* Add enters to the end of files.
* Removing target and setting source of events to be the application instead of the main window. The main window isn't the game window, and I don't really know what widget will be targetted for the game event. Works, though, it's admittedly probably not optimal by ANY means.
* Fix comment.
* Fix libpng wit zlib.
* Move Qt GUI into RPCS3Qt. (#17)
Restore wx GUI.
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* Add stylesheet to git ignore.
* XInput..
* Joystick...
* Rpcs3 qt small fixes (#20)
* Small fixes. Have emulator stop when x button is pressed on game window. Have emulator/application stop when the main window is closed.
* If I forget another new line ending for a file.............................................
* Add CgDisasm (#21)
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* add CgDisasm
add code to disable contextmenu options
fix gamelist issue
* missing proj changes
* Add ability to open stylesheets from menu.
* Mega searcher (#23)
* add MemoryStringSearcher
set minimum Sizes for mainwindow and CgDisasm
* minor fixes
* Since the system.cpp callbacks for emulator state were unused, I removed them. Then, I replaced them with callbacks for the Gui.
* added stylesheet options
setfocus on settings fixed
newline added
* added signals and slots for EmuRun and EmuStop
* update ui
update ui now works
added callback onReady
added EnableMenues
added ps3 commands
* added restart logic to menu
* newline
* event header removed
* Added graphic settings class. (#26)
* Added graphic settings class. First thing is to have the dock widgets and window size/location be stateful. Minor bug with debugger frame changing size on hide/show on default setup on second load. But, otherwise, fine. Also, the GUI doesn't update to accomodate the statefulness of the widgets. But, that'll come in time as I update this class.
* Add view debugger, logger, gamelist to settings and synchronize them.
* Separate initializing actions from connects
* Add invisible fullscreen cursor and double click event.
* Add the UI log settings.
* Add MemoryViewer (#30)
* Add Memoryviewer
Image Button crashes/not fully implemented
focus on some button annoying
minor changes for question dialogs
* GuiSettings Refactoring (#31)
* Add settings for columns shown and which one is saved
* I accidentally refactored the settings class. Added ability to reset to default GUI. Added statefulness to column widths.
* add gui tab
* Fix logging at startup.
* Preset settings.I think I ironed out MOST of the glitches. Will work on the rest of it soon. Should be a lot simpler as I won't have to use the so-called meta settings. Also, renamed all settings methods to CapitalCase.
* Removed dock widget controls.
* Added style sheets. Removed the option from the menu.
* Rewrite to use folder design. Much simpler! Yay! Simpler. Better, right?
* It's remarkable how tricky this is.
* Added convenience button to open up the settings folder in explorer
* Add newlines at end of file
* simplified logic. Fixed a bug.. hopefully not more bugs
* Fix the undocumented feature
* Make the dialog big enough to have entire text on title shown. If talkashie changes the font to size 1203482 I don't care lol
* Make warning messagebox instead of changing the title of the dialog.
* marking...
* Hcorion suggested changes.
* [WIP] autopause (#32)
* autopause added
needs fixing
headers do not show text
* fix compile stuff
* Add MsgDialog + edge widgets (#33)
* Add MsgDialog
needs magic
* add "Debugger" Buttons to menubar
* Adapt ds4 changes. I'm not sure if they work as I don't have a compatible controller. But, at the same time, it's kind of silly all I had to do was remove stdguiafx to get compilation.
* [Ready] Add KernelExplorer (#36)
* KernelExplorer added
* Fix build. Connect mainwindow to show explorer.
* qstr formatting added
hid header, fixed button size
* Taskbar Progress for install PUP/PKG (#37)
* Add Taskbar Progress for both PKG and PUP installer
* fix missing ifdefs for windows
* add mainwindow icon + thumbnail toolbar
* add game specific icons to the GSFrame
* fix icon crash
* fix appIcon's aspect ratio in SetAppIconFromPath
* Fix black borders in RGB32 icons
* rename thumbar related buttons
* EmuSettings (#35)
* Core tab done minus doing the library list.
* Graphics tab.
* Audio tab
* Input tab
* Added the other tabs
* LLE part one-- load existing libraries sorted. (I'd finish it but I'm going to look at a PR by mega)
* add search and add other libraries that aren't checked.
* Finish adding lle selecting things.
* marking my territory (#38)
fixed settingsdialog glitch and width
added groupbox to gui buttons
removed parents from layouts
* add debuggerframe + RSXDebugger (#34)
* Add Debuggerframe
* add RSXDebugger
* add RSXDebugger fo real
* RSXDebugger improved
minor adjustments
* add utf8 conversions like neko told me to
hopefully i did not utf8-ise too many things xD
* fix some variables
* maybe fix image buffers in RSXDebugger
* fixed image view (pretty sure)
* fixed image buffer (hopefully)
* QT Opengl frame (#41)
* fix RSX Debugger headers (#40)
* fix some debugger layout issues
fix RSX Debugger headers + some comments
* add kd-11's SPU options
fix D3D12 showing on non-compatible systems
tidy up coretab
* improve D3D12 behaviour in graphicstab:
adapter selection and D3D12 render won't show on non-compatible systems
add monospace font to cgDisasm
* enable update only on visibility
* Rpcs3 qt llvm build (#42)
* LLVM pushed so mega can test
* probably is what is needed with Release LLVM
* should probably have RPCS3-Qt be using release-llvm
* include zlib the same way.
* don't talk to me about how I made this happen.
* I applied the magical treatment to debug mode too. Though, it's entirely probably that doing it once in LLVM-release mode made this entirely redundant
* hack
* progress bar for LLVM spawns but doesn't close yet.
* fix msgDialog (#43)
fix oskDialog
* Minor bug fixzz
* fix osk and msgdialog for real (#44)
* fix msgDialog
fix oskDialog
* fix OskDialog part 2
fix MsgDialog part 2
* This bug is evil, and it should be ashamed of itself.
* Refactor YAML. Commented out gui options that aren't added to config yet (add em back later when we merge that in)
* Fix pad stuff.
* add SaveDataUtility (#45)
* add SaveDataUtility
* fix slots
* fix slots again
fix lists not showing stuff
fix dialogs not showing
add colClicked
refactor stuff and polish some layouts
* add SaveDataDialog.h and SaveDataDialog.cpp
* tidy up mainwindow
* add callback
* fix RegisterEditor (#47)
* fix RegisterEditor
* fix other dialogs' immortality (gasp...vampires)
* remove debug leftovers
* fix InstructionEditor (#46)
* fix InstructionEditor
* fix typo
* Fix MouseClickEvents in RSXDebugger (#50)
* Fix MouseClickEvents in RSXDebugger
Fix focus on MemoryViewer and RSXDebugger
Adjust PadButtonWidth
* fix another comment
* fix debuggerframe events (#49)
* Fix pad settings bro (#48)
* Fix pad settings bro
* fix comment
* Icons and Menu-Additions (#39)
* Add Icons and iconlogic to cornerWidget and actions
* add cornerWidget toggle
fix dockwidget action state on start
remove DoSettings
* fix game removal bug
remove tableitem focus rectangle
therefore add TableItemDelegate.h
* remove grid and focus rectangle from autopausedialog
* add fullscreen checkbox to misctab
minor padsettings layout improvements
* Add show category submenu to view menu
Add gamelist filter accordingly
fix minor bug where play icon was displayed despite pause label
add boolean b_fullscreen to mainwindow for later use in GSFrame
* fix headers in autopausesettings
fix remove bug in autopausesettings
add delete keypressevent in autopausesettings
fix missing tr() and minor refactoring in gamelist
* add default Icons for play/pause/stop/restart
* Fix fullscreen start. Some stuff was wrong with settings, just trust me.
* remove fullscreen leftovers and fix merge
* SPU stuff. (There was also a weird thing with config.h in GLGSFrame.h with an include that I removed to fix build)
* please neko's lambda fetishes (#53)
* please neko's lambda fetish in mainwindow
* please neko's lambda fetish in gamelistframe
* please neko's lambda fetish in logframe
* fix neko's lambda fetish in debuggerframe
* pleasefixdofetishsomething in Autopausesettingsdialog
* fix sth sth lambda in cg disasm
* lambda stuff in instructioneditor
* lambda kernelexplorer
* lambda-ise memoryviewer
* lambda rsxdebugger
* lambda savedatautil
this could be done even more, but the functions are not implemented
* Rpcs3 qt fixes -- shadow taskbar bug (#52)
* SShadow's bug of taskbar progress staying fixed on cancelling pkg install.
* other taskbar
* i'm still a baka
* Fix a warning
* qtQt refactoring (#54)
* fix neko's snake fetish
* File names should match headers. Are these the names I want? Not necessarily. But, this is much less confusing.
* i thought I committed everything with stage all.........................
* remove unused utilities
* The most important commit of them all.
* Disable legacy opengl buffers when not using opengl.
* fix code review comment
* Quick crash patch. Neko removed autopause. SO, I remove it too from emusettings/misc tab
* Merge lovely things from master (#55)
* Configuration simplified
* untrivial parts of the merge
* no need for these options anymore
* Minor change to fix column widths at startup (not sure why it doesn't work already, but adding the true makes it work so......... whatever)
* here ya go
* FIx hitting okay in settings causing graphics to messup (#57)
* fixes + msgdialog taskbarprogress (#56)
* fix ok button in taskbar
add taskicon progressbar for msgdialog
add tablewidgetitem to rsxdebugger
fix comments in save_data_utility.cpp
* fix d3d adapter default
* fix taskicon progressbar not being destroyed properly
* add last_path to filedialogs
* fix msgdialog crash on ok (#58)
* fix thread stopping in debbugerFrame (#59)
* Move Emu.init to be first. This will fix the qt stuff seeming to ignore the virtual filesystem in the config. (VFS to be made soon maybe) (#60)
* Fix full screen opening on double RIGHT click.
* fix other instances of double click ...
* Fix locaiton of gui config. (#61)
* fix d3d bug (#62)
* fix d3d bug
* small utf8 addition
* Fix cmake for qt (#64)
* Initial CMake fix
* Fix compilation with GCC
* Get rid of awful hack
* Update cotire with qt support
* Maybe fix travis
* Emergency Hack Relief Program Activated
* Fix travis build (#65)
* make about dialog great again (#67)
and add previous additions
* Fix library sort / smart gamelist context menu (#63)
* fix library sort
* add Title to custom game config dialog
* disable options on gamelist context menu
* use namespace for category Strings
* introduce sstr
* fix some tr nonsense
* Rpcs3qt Appveyor (#68)
Fix appyveyor build!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* possible fix for gamelist icons (#69)
add warning for appicon
* Fix clang build (#66)
Hcorion, the build savior.
* Rpcs3 qt resources (#70)
* Resource files attempt 1
* Autorcc should probably be on?
* forgot the most important file lol
* Forgot an instance of the icon in the code...
* Patch fix for clang build.
* vulkan/d3d12 combobox merge (#71)
* add vulkan adapterbox and merge with d3d12 box
* fix adapter text on other renderer
* gather render strings
* attempt fix on gamelist row height
* adjust adapter behaviour to new guideline
* Compiler of Peace.
* High critical hit rate.
* Mugi eating strawberries is savage.
* Apply KD-11 Hotfix (#73)
* Most of Ani Adjusts (#72)
* Most of the adjustments are made here.
* fix gamelist rowheight
* fix msg dialog layout and disable_cancel
* cleanup
* fix disable cancle again
* fix debuggerframe buttons and doubleclick
* Add a fun little bonus feature :) (#74)
* category filters simplyfied (#75)
* Cleaning up cmake a bit.
* fixezzzzzz (#76)
* upgrade Info Boxes
* upgrade file explorer
* refactor GetSettings and SetSettings
* second refactoring
* cleanup
* travis is a grammar nazi
* second travis shenanigans
* third travis weirdo thingy
* travis 4 mega fun
* travis 5 default to def
* finish refactoring for settings
fix gamelist headers
* hotfix msgdialog and infobox (#77)
* msgdialog fix 1
* fix zombie infobox
* Rpcs3 Qt Welcome Page (#78)
* Add a welcome dialog.
* Add enter to end of file
* i'm an idiot
* last mistake i hope
* sponsored via --> funded by
* RPCS3 does not condone piracy.
* Mega Adjusts
* Ani Adjustments and a few refactorings
* Yay
* Add Gamelist Icon Sizes (#79)
* Reverting Mega's suggestion. If people can use alt-f4 to get around this dialog, they can probably use an emulator too.
* Fix firmware file choice dialog in QT GUI (#80)
* ani adjusts 2 + minor icon size simplifications (#81)
FPS Additions
* Update Travis to Qt 5.9 (#82)
2017-06-04 16:48:33 +02:00
|
|
|
|
GetCallbacks().on_pause();
|
2015-10-13 19:32:08 +02:00
|
|
|
|
|
2021-09-07 08:27:23 +02:00
|
|
|
|
static atomic_t<u32> pause_mark = 0;
|
|
|
|
|
|
|
2021-09-07 18:42:08 +02:00
|
|
|
|
if (freeze_emulation)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.warning("Emulation has been frozen! You can either use debugger tools to inspect current emulation state or terminate it.");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.success("Emulation is being paused... (mark=%u)", pause_mark++);
|
|
|
|
|
|
}
|
2021-09-07 08:27:23 +02:00
|
|
|
|
|
2016-04-14 00:59:00 +02:00
|
|
|
|
// Update pause start time
|
2015-07-04 21:23:10 +02:00
|
|
|
|
if (m_pause_start_time.exchange(start))
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.error("Emulator::Pause() error: concurrent access");
|
2015-07-04 21:23:10 +02:00
|
|
|
|
}
|
2015-07-01 00:25:52 +02:00
|
|
|
|
|
2017-01-29 17:50:18 +01:00
|
|
|
|
auto on_select = [](u32, cpu_thread& cpu)
|
2015-07-04 21:23:10 +02:00
|
|
|
|
{
|
2016-08-09 16:14:41 +02:00
|
|
|
|
cpu.state += cpu_flag::dbg_global_pause;
|
2017-01-29 17:50:18 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
2018-10-11 00:17:19 +02:00
|
|
|
|
idm::select<named_thread<ppu_thread>>(on_select);
|
|
|
|
|
|
idm::select<named_thread<spu_thread>>(on_select);
|
2021-01-28 18:23:13 +01:00
|
|
|
|
|
2021-02-03 19:14:31 +01:00
|
|
|
|
if (auto rsx = g_fxo->try_get<rsx::thread>())
|
2021-01-28 18:23:13 +01:00
|
|
|
|
{
|
|
|
|
|
|
rsx->state += cpu_flag::dbg_global_pause;
|
|
|
|
|
|
}
|
2019-10-12 14:40:47 +02:00
|
|
|
|
|
2020-07-03 17:12:58 +02:00
|
|
|
|
// Always Enable display sleep, not only if it was prevented.
|
|
|
|
|
|
enable_display_sleep();
|
2019-10-12 14:40:47 +02:00
|
|
|
|
|
2015-09-13 00:37:57 +02:00
|
|
|
|
return true;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Emulator::Resume()
|
|
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
if (m_state != system_state::paused)
|
2015-07-06 01:21:15 +02:00
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
return;
|
2015-07-06 01:21:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-10-05 23:24:50 +02:00
|
|
|
|
// Print and reset debug data collected
|
2022-08-26 11:23:29 +02:00
|
|
|
|
if (g_cfg.core.ppu_decoder == ppu_decoder_type::_static && g_cfg.core.ppu_debug)
|
2017-10-05 23:24:50 +02:00
|
|
|
|
{
|
2021-01-22 09:11:54 +01:00
|
|
|
|
PPUDisAsm dis_asm(cpu_disasm_mode::dump, vm::g_sudo_addr);
|
2017-10-05 23:24:50 +02:00
|
|
|
|
|
|
|
|
|
|
std::string dump;
|
|
|
|
|
|
|
2021-03-02 19:07:24 +01:00
|
|
|
|
for (u32 i = 0x10000; i < 0xE0000000;)
|
2017-10-05 23:24:50 +02:00
|
|
|
|
{
|
2021-02-26 10:20:25 +01:00
|
|
|
|
if (vm::check_addr(i, vm::page_executable))
|
2017-10-05 23:24:50 +02:00
|
|
|
|
{
|
2019-12-02 22:31:34 +01:00
|
|
|
|
if (auto& data = *reinterpret_cast<be_t<u32>*>(vm::g_stat_addr + i))
|
2017-10-05 23:24:50 +02:00
|
|
|
|
{
|
|
|
|
|
|
dis_asm.disasm(i);
|
|
|
|
|
|
fmt::append(dump, "\n\t'%08X' %s", data, dis_asm.last_opcode);
|
|
|
|
|
|
data = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
i += sizeof(u32);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
i += 4096;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-26 11:23:29 +02:00
|
|
|
|
if (!dump.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
ppu_log.notice("[RESUME] Dumping instruction stats:%s", dump);
|
|
|
|
|
|
}
|
2017-10-05 23:24:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-04-14 00:59:00 +02:00
|
|
|
|
// Try to resume
|
2017-05-20 13:45:02 +02:00
|
|
|
|
if (!m_state.compare_and_swap_test(system_state::paused, system_state::running))
|
2015-07-04 21:23:10 +02:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
// Get pause start time
|
|
|
|
|
|
const u64 time = m_pause_start_time.exchange(0);
|
|
|
|
|
|
|
|
|
|
|
|
// Try to increment summary pause time
|
|
|
|
|
|
if (time)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pause_amend_time += get_system_time() - time;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
2015-07-04 21:23:10 +02:00
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.error("Emulator::Resume() error: concurrent access");
|
2015-07-04 21:23:10 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
perf_stat_base::report();
|
|
|
|
|
|
|
2017-02-05 14:35:10 +01:00
|
|
|
|
auto on_select = [](u32, cpu_thread& cpu)
|
2015-07-01 00:25:52 +02:00
|
|
|
|
{
|
2017-02-05 14:35:10 +01:00
|
|
|
|
cpu.state -= cpu_flag::dbg_global_pause;
|
2021-02-13 15:50:07 +01:00
|
|
|
|
cpu.state.notify_one(cpu_flag::dbg_global_pause);
|
2017-02-05 14:35:10 +01:00
|
|
|
|
};
|
2016-09-07 00:38:52 +02:00
|
|
|
|
|
2018-10-11 00:17:19 +02:00
|
|
|
|
idm::select<named_thread<ppu_thread>>(on_select);
|
|
|
|
|
|
idm::select<named_thread<spu_thread>>(on_select);
|
2021-01-28 18:23:13 +01:00
|
|
|
|
|
2021-02-03 19:14:31 +01:00
|
|
|
|
if (auto rsx = g_fxo->try_get<rsx::thread>())
|
2021-01-28 18:23:13 +01:00
|
|
|
|
{
|
|
|
|
|
|
// TODO: notify?
|
|
|
|
|
|
rsx->state -= cpu_flag::dbg_global_pause;
|
|
|
|
|
|
}
|
2021-01-22 09:11:54 +01:00
|
|
|
|
|
RPCS3 QT (#2645)
* Fix windows build. I made sure to do everything with a win32 prefix to not effect linux build.
* Make the window resizable instead of fixed in the corner.
* Ignore moc files and things in the debug/release folder. I might also ignore rpcs3qt.vcxproj and its filters as they're autogenerated by importing the qt project file. But, this helps clean out clutter for now.
* Add cmake. This doesn't interact with the rest of rpcs3 nor the main cmake file. That's the next thing I'm doing. I'll probably need to modify them so it'll take me time to figure out. But, this will build rpcs3qt on linux and build as is with using qt.
* The build works. I'd like to thank my friends, Google and Stackoverflow.
Setted up by importing rpcs3Qt project using Qt's visual studio plugin.
* Cleanup. Remove all the stuff in the rpcs3qt folder as its incorporated elsewhere. Remove the rpcs3qt project file as its now built into the solution and cmake doesn't care about pro files.
* Update readme to reflect getting Qt.
* Remove wxwidgets as submodule and add zlib instead. Wxwidgets was our old way of having zlib. I also added build dependencies to rpcs3qt so you should no longer get link errors on the first clean rebuild.
* Add rpcs3_version, few GUI tweaks
* Set defaultSize to 70% of screen size
* Add the view menu (#3)
* Added the view menu with the corresponding elements. Now, the debugger/log are hidden by default. The view menu has a checkbox which you click to show/hide the dock widgets.
* Make log visible by default
* Improve UI by making it into a checkbox that's easier to use.
* fix qt build for vs2017 (seems to work fine in 2015 with plugin but needs testing by other users)
* updated readme for qt
* update appveyor for qt
- cleaned formatting for the post build command
* fix build (#6)
* fix build legit this time i promise
* [Ready] Gamepadsettings (#4)
* WIP Gamepadsettings
pushbutton Eventhandling missing
* GamepadSettings should work except for cfg Init
Some KeyInputs are missing
* Update padsettingsdialog.h
* Update padsettingsdialog.cpp (#5)
* Update padsettingsdialog.cpp
removed silly tabs
* Update padsettingsdialog.cpp
* GetKeyCode simplified
* rename pad settings to keyboard settings o.O
* rename keyboard setting to input settings
* Remvoed the QT_UI defines.
* Readded new line at end of file. Replaced define in padsettings with constant.
* GUI fixes (Settings)
* Stub the logger UI. Nothing special besides a simple stub.
* Unstub the log. I haven't tested TTY but it should work.
Only thing to do, but this is in general, is add persistent settings.
* Minor refactoring to simplify code.
* Fix image loading. I'm 90% sure it works because it loads the path as expected and that's the same format I used in my gamelist implementation for the images.
* Made game lists much more functional than it was.
* mainwindow
* gamelist
* Please forgive me for I have lambdaed.
Added the ability to toggle showing columns via a context menu.
* Fix GameList further
* sort by name on init fixed
* Created the baseline refactoring. I'm going to start working on the callbacks now. May need to implement other classes in the process. Fun stuff, I know.
* adds InstallPkg (tested) and InstallPup (should work but makes unknown shenanigans) implementation
adds RefreshGameList
obliterates 10sec Refresh
* messages
* Rpcs3 gs frame (#16)
* Messing with project settings try to get trails of cold steel to boot.bluh
Definitely one change is needed in linker settings for RPCS3 to not crash immediately.
Can't even see how horribly botched my implementation of GSFrame is because we aren't booting lol. Something is gone awry with elf.
* remove random ! not that it matters much right now
* minor additions
* "Working" with debug mode though you have to ignore an assert reached from Qt. Qt is upset that the rsx thread is calling stuff on the UI thread despite not owning it. However, I can't do a thing to change that atm. (The fix would be to do what the TODO says in System.cpp-- making gsframe and stuff get initialized via system call)
Crashes due to needing pad callback to be done.
* With this build in debug mode, Trails of Cold steel will get FPS. (caveat. You have to ignore when Qt throws a debug assert lol)
* Fix release mode. Fix the Qt debug assert by using ancient occault rituals. I want to be able to remove the blocking connects but it won't work right now without it. It isn't perfect but it's good enough for now IMO.
* Add enters to the end of files.
* Removing target and setting source of events to be the application instead of the main window. The main window isn't the game window, and I don't really know what widget will be targetted for the game event. Works, though, it's admittedly probably not optimal by ANY means.
* Fix comment.
* Fix libpng wit zlib.
* Move Qt GUI into RPCS3Qt. (#17)
Restore wx GUI.
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* Add stylesheet to git ignore.
* XInput..
* Joystick...
* Rpcs3 qt small fixes (#20)
* Small fixes. Have emulator stop when x button is pressed on game window. Have emulator/application stop when the main window is closed.
* If I forget another new line ending for a file.............................................
* Add CgDisasm (#21)
* fix install-progressdialogs randomly not showing
* install-progressdialog cosmetics
* add stylesheet file loading
* apply request
* add CgDisasm
add code to disable contextmenu options
fix gamelist issue
* missing proj changes
* Add ability to open stylesheets from menu.
* Mega searcher (#23)
* add MemoryStringSearcher
set minimum Sizes for mainwindow and CgDisasm
* minor fixes
* Since the system.cpp callbacks for emulator state were unused, I removed them. Then, I replaced them with callbacks for the Gui.
* added stylesheet options
setfocus on settings fixed
newline added
* added signals and slots for EmuRun and EmuStop
* update ui
update ui now works
added callback onReady
added EnableMenues
added ps3 commands
* added restart logic to menu
* newline
* event header removed
* Added graphic settings class. (#26)
* Added graphic settings class. First thing is to have the dock widgets and window size/location be stateful. Minor bug with debugger frame changing size on hide/show on default setup on second load. But, otherwise, fine. Also, the GUI doesn't update to accomodate the statefulness of the widgets. But, that'll come in time as I update this class.
* Add view debugger, logger, gamelist to settings and synchronize them.
* Separate initializing actions from connects
* Add invisible fullscreen cursor and double click event.
* Add the UI log settings.
* Add MemoryViewer (#30)
* Add Memoryviewer
Image Button crashes/not fully implemented
focus on some button annoying
minor changes for question dialogs
* GuiSettings Refactoring (#31)
* Add settings for columns shown and which one is saved
* I accidentally refactored the settings class. Added ability to reset to default GUI. Added statefulness to column widths.
* add gui tab
* Fix logging at startup.
* Preset settings.I think I ironed out MOST of the glitches. Will work on the rest of it soon. Should be a lot simpler as I won't have to use the so-called meta settings. Also, renamed all settings methods to CapitalCase.
* Removed dock widget controls.
* Added style sheets. Removed the option from the menu.
* Rewrite to use folder design. Much simpler! Yay! Simpler. Better, right?
* It's remarkable how tricky this is.
* Added convenience button to open up the settings folder in explorer
* Add newlines at end of file
* simplified logic. Fixed a bug.. hopefully not more bugs
* Fix the undocumented feature
* Make the dialog big enough to have entire text on title shown. If talkashie changes the font to size 1203482 I don't care lol
* Make warning messagebox instead of changing the title of the dialog.
* marking...
* Hcorion suggested changes.
* [WIP] autopause (#32)
* autopause added
needs fixing
headers do not show text
* fix compile stuff
* Add MsgDialog + edge widgets (#33)
* Add MsgDialog
needs magic
* add "Debugger" Buttons to menubar
* Adapt ds4 changes. I'm not sure if they work as I don't have a compatible controller. But, at the same time, it's kind of silly all I had to do was remove stdguiafx to get compilation.
* [Ready] Add KernelExplorer (#36)
* KernelExplorer added
* Fix build. Connect mainwindow to show explorer.
* qstr formatting added
hid header, fixed button size
* Taskbar Progress for install PUP/PKG (#37)
* Add Taskbar Progress for both PKG and PUP installer
* fix missing ifdefs for windows
* add mainwindow icon + thumbnail toolbar
* add game specific icons to the GSFrame
* fix icon crash
* fix appIcon's aspect ratio in SetAppIconFromPath
* Fix black borders in RGB32 icons
* rename thumbar related buttons
* EmuSettings (#35)
* Core tab done minus doing the library list.
* Graphics tab.
* Audio tab
* Input tab
* Added the other tabs
* LLE part one-- load existing libraries sorted. (I'd finish it but I'm going to look at a PR by mega)
* add search and add other libraries that aren't checked.
* Finish adding lle selecting things.
* marking my territory (#38)
fixed settingsdialog glitch and width
added groupbox to gui buttons
removed parents from layouts
* add debuggerframe + RSXDebugger (#34)
* Add Debuggerframe
* add RSXDebugger
* add RSXDebugger fo real
* RSXDebugger improved
minor adjustments
* add utf8 conversions like neko told me to
hopefully i did not utf8-ise too many things xD
* fix some variables
* maybe fix image buffers in RSXDebugger
* fixed image view (pretty sure)
* fixed image buffer (hopefully)
* QT Opengl frame (#41)
* fix RSX Debugger headers (#40)
* fix some debugger layout issues
fix RSX Debugger headers + some comments
* add kd-11's SPU options
fix D3D12 showing on non-compatible systems
tidy up coretab
* improve D3D12 behaviour in graphicstab:
adapter selection and D3D12 render won't show on non-compatible systems
add monospace font to cgDisasm
* enable update only on visibility
* Rpcs3 qt llvm build (#42)
* LLVM pushed so mega can test
* probably is what is needed with Release LLVM
* should probably have RPCS3-Qt be using release-llvm
* include zlib the same way.
* don't talk to me about how I made this happen.
* I applied the magical treatment to debug mode too. Though, it's entirely probably that doing it once in LLVM-release mode made this entirely redundant
* hack
* progress bar for LLVM spawns but doesn't close yet.
* fix msgDialog (#43)
fix oskDialog
* Minor bug fixzz
* fix osk and msgdialog for real (#44)
* fix msgDialog
fix oskDialog
* fix OskDialog part 2
fix MsgDialog part 2
* This bug is evil, and it should be ashamed of itself.
* Refactor YAML. Commented out gui options that aren't added to config yet (add em back later when we merge that in)
* Fix pad stuff.
* add SaveDataUtility (#45)
* add SaveDataUtility
* fix slots
* fix slots again
fix lists not showing stuff
fix dialogs not showing
add colClicked
refactor stuff and polish some layouts
* add SaveDataDialog.h and SaveDataDialog.cpp
* tidy up mainwindow
* add callback
* fix RegisterEditor (#47)
* fix RegisterEditor
* fix other dialogs' immortality (gasp...vampires)
* remove debug leftovers
* fix InstructionEditor (#46)
* fix InstructionEditor
* fix typo
* Fix MouseClickEvents in RSXDebugger (#50)
* Fix MouseClickEvents in RSXDebugger
Fix focus on MemoryViewer and RSXDebugger
Adjust PadButtonWidth
* fix another comment
* fix debuggerframe events (#49)
* Fix pad settings bro (#48)
* Fix pad settings bro
* fix comment
* Icons and Menu-Additions (#39)
* Add Icons and iconlogic to cornerWidget and actions
* add cornerWidget toggle
fix dockwidget action state on start
remove DoSettings
* fix game removal bug
remove tableitem focus rectangle
therefore add TableItemDelegate.h
* remove grid and focus rectangle from autopausedialog
* add fullscreen checkbox to misctab
minor padsettings layout improvements
* Add show category submenu to view menu
Add gamelist filter accordingly
fix minor bug where play icon was displayed despite pause label
add boolean b_fullscreen to mainwindow for later use in GSFrame
* fix headers in autopausesettings
fix remove bug in autopausesettings
add delete keypressevent in autopausesettings
fix missing tr() and minor refactoring in gamelist
* add default Icons for play/pause/stop/restart
* Fix fullscreen start. Some stuff was wrong with settings, just trust me.
* remove fullscreen leftovers and fix merge
* SPU stuff. (There was also a weird thing with config.h in GLGSFrame.h with an include that I removed to fix build)
* please neko's lambda fetishes (#53)
* please neko's lambda fetish in mainwindow
* please neko's lambda fetish in gamelistframe
* please neko's lambda fetish in logframe
* fix neko's lambda fetish in debuggerframe
* pleasefixdofetishsomething in Autopausesettingsdialog
* fix sth sth lambda in cg disasm
* lambda stuff in instructioneditor
* lambda kernelexplorer
* lambda-ise memoryviewer
* lambda rsxdebugger
* lambda savedatautil
this could be done even more, but the functions are not implemented
* Rpcs3 qt fixes -- shadow taskbar bug (#52)
* SShadow's bug of taskbar progress staying fixed on cancelling pkg install.
* other taskbar
* i'm still a baka
* Fix a warning
* qtQt refactoring (#54)
* fix neko's snake fetish
* File names should match headers. Are these the names I want? Not necessarily. But, this is much less confusing.
* i thought I committed everything with stage all.........................
* remove unused utilities
* The most important commit of them all.
* Disable legacy opengl buffers when not using opengl.
* fix code review comment
* Quick crash patch. Neko removed autopause. SO, I remove it too from emusettings/misc tab
* Merge lovely things from master (#55)
* Configuration simplified
* untrivial parts of the merge
* no need for these options anymore
* Minor change to fix column widths at startup (not sure why it doesn't work already, but adding the true makes it work so......... whatever)
* here ya go
* FIx hitting okay in settings causing graphics to messup (#57)
* fixes + msgdialog taskbarprogress (#56)
* fix ok button in taskbar
add taskicon progressbar for msgdialog
add tablewidgetitem to rsxdebugger
fix comments in save_data_utility.cpp
* fix d3d adapter default
* fix taskicon progressbar not being destroyed properly
* add last_path to filedialogs
* fix msgdialog crash on ok (#58)
* fix thread stopping in debbugerFrame (#59)
* Move Emu.init to be first. This will fix the qt stuff seeming to ignore the virtual filesystem in the config. (VFS to be made soon maybe) (#60)
* Fix full screen opening on double RIGHT click.
* fix other instances of double click ...
* Fix locaiton of gui config. (#61)
* fix d3d bug (#62)
* fix d3d bug
* small utf8 addition
* Fix cmake for qt (#64)
* Initial CMake fix
* Fix compilation with GCC
* Get rid of awful hack
* Update cotire with qt support
* Maybe fix travis
* Emergency Hack Relief Program Activated
* Fix travis build (#65)
* make about dialog great again (#67)
and add previous additions
* Fix library sort / smart gamelist context menu (#63)
* fix library sort
* add Title to custom game config dialog
* disable options on gamelist context menu
* use namespace for category Strings
* introduce sstr
* fix some tr nonsense
* Rpcs3qt Appveyor (#68)
Fix appyveyor build!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* possible fix for gamelist icons (#69)
add warning for appicon
* Fix clang build (#66)
Hcorion, the build savior.
* Rpcs3 qt resources (#70)
* Resource files attempt 1
* Autorcc should probably be on?
* forgot the most important file lol
* Forgot an instance of the icon in the code...
* Patch fix for clang build.
* vulkan/d3d12 combobox merge (#71)
* add vulkan adapterbox and merge with d3d12 box
* fix adapter text on other renderer
* gather render strings
* attempt fix on gamelist row height
* adjust adapter behaviour to new guideline
* Compiler of Peace.
* High critical hit rate.
* Mugi eating strawberries is savage.
* Apply KD-11 Hotfix (#73)
* Most of Ani Adjusts (#72)
* Most of the adjustments are made here.
* fix gamelist rowheight
* fix msg dialog layout and disable_cancel
* cleanup
* fix disable cancle again
* fix debuggerframe buttons and doubleclick
* Add a fun little bonus feature :) (#74)
* category filters simplyfied (#75)
* Cleaning up cmake a bit.
* fixezzzzzz (#76)
* upgrade Info Boxes
* upgrade file explorer
* refactor GetSettings and SetSettings
* second refactoring
* cleanup
* travis is a grammar nazi
* second travis shenanigans
* third travis weirdo thingy
* travis 4 mega fun
* travis 5 default to def
* finish refactoring for settings
fix gamelist headers
* hotfix msgdialog and infobox (#77)
* msgdialog fix 1
* fix zombie infobox
* Rpcs3 Qt Welcome Page (#78)
* Add a welcome dialog.
* Add enter to end of file
* i'm an idiot
* last mistake i hope
* sponsored via --> funded by
* RPCS3 does not condone piracy.
* Mega Adjusts
* Ani Adjustments and a few refactorings
* Yay
* Add Gamelist Icon Sizes (#79)
* Reverting Mega's suggestion. If people can use alt-f4 to get around this dialog, they can probably use an emulator too.
* Fix firmware file choice dialog in QT GUI (#80)
* ani adjusts 2 + minor icon size simplifications (#81)
FPS Additions
* Update Travis to Qt 5.9 (#82)
2017-06-04 16:48:33 +02:00
|
|
|
|
GetCallbacks().on_resume();
|
2019-10-12 14:40:47 +02:00
|
|
|
|
|
2021-09-07 08:27:23 +02:00
|
|
|
|
sys_log.success("Emulation has been resumed!");
|
|
|
|
|
|
|
2019-10-12 14:40:47 +02:00
|
|
|
|
if (g_cfg.misc.prevent_display_sleep)
|
|
|
|
|
|
{
|
|
|
|
|
|
disable_display_sleep();
|
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-30 15:31:01 +02:00
|
|
|
|
s32 sysutil_send_system_cmd(u64 status, u64 param);
|
2022-06-06 16:16:32 +02:00
|
|
|
|
u64 get_sysutil_cb_manager_read_count();
|
|
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
void process_qt_events();
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savestate)
|
2012-11-15 00:39:56 +01:00
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
const auto old_state = m_state.load();
|
|
|
|
|
|
|
|
|
|
|
|
if (old_state == system_state::stopped)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (old_state == system_state::paused)
|
|
|
|
|
|
{
|
|
|
|
|
|
Resume();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-06 16:16:32 +02:00
|
|
|
|
const u64 read_counter = get_sysutil_cb_manager_read_count();
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (old_state == system_state::frozen || savestate || !sysutil_send_system_cmd(0x0101 /* CELL_SYSUTIL_REQUEST_EXITGAME */, 0))
|
2022-02-05 11:49:29 +01:00
|
|
|
|
{
|
|
|
|
|
|
// The callback has been rudely ignored, we have no other option but to force termination
|
2022-07-04 15:02:17 +02:00
|
|
|
|
Kill(allow_autoexit && !savestate, savestate);
|
2022-02-05 11:49:29 +01:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-06 16:16:32 +02:00
|
|
|
|
auto perform_kill = [read_counter, allow_autoexit, this, info = ProcureCurrentEmulationCourseInformation()]()
|
2015-07-04 21:23:10 +02:00
|
|
|
|
{
|
2022-06-06 16:16:32 +02:00
|
|
|
|
bool read_sysutil_signal = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (u32 i = 100; i < 140; i++)
|
2018-09-19 20:54:55 +02:00
|
|
|
|
{
|
2022-02-05 11:49:29 +01:00
|
|
|
|
std::this_thread::sleep_for(50ms);
|
|
|
|
|
|
Resume(); // TODO: Prevent pausing by other threads while in this loop
|
|
|
|
|
|
process_qt_events(); // Is nullified when performed on non-main thread
|
|
|
|
|
|
|
2022-06-06 16:16:32 +02:00
|
|
|
|
if (!read_sysutil_signal && read_counter != get_sysutil_cb_manager_read_count())
|
|
|
|
|
|
{
|
|
|
|
|
|
i -= 100; // Grant 5 seconds (if signal is not read force kill after two second)
|
|
|
|
|
|
read_sysutil_signal = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
if (static_cast<u64>(info) != m_stop_ctr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2018-09-19 20:54:55 +02:00
|
|
|
|
}
|
2018-09-25 20:12:17 +02:00
|
|
|
|
|
2022-06-06 16:16:32 +02:00
|
|
|
|
// An inevitable attempt to terminate the *current* emulation course will be issued after 7s
|
2022-01-20 18:44:49 +01:00
|
|
|
|
CallFromMainThread([allow_autoexit, this]()
|
2022-02-05 11:49:29 +01:00
|
|
|
|
{
|
|
|
|
|
|
Kill(allow_autoexit);
|
|
|
|
|
|
}, info);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (async_op)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::thread{perform_kill}.detach();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
perform_kill();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
extern bool try_lock_vdec_context_creation();
|
2022-07-14 21:07:02 +02:00
|
|
|
|
extern bool try_lock_spu_threads_in_a_state_compatible_with_savestates();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
std::shared_ptr<utils::serial> Emulator::Kill(bool allow_autoexit, bool savestate)
|
2022-02-05 11:49:29 +01:00
|
|
|
|
{
|
2022-07-15 21:11:39 +02:00
|
|
|
|
std::shared_ptr<utils::serial> to_ar;
|
|
|
|
|
|
|
2022-07-14 21:07:02 +02:00
|
|
|
|
if (savestate && !try_lock_spu_threads_in_a_state_compatible_with_savestates())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to savestate: failed to lock SPU threads execution.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-05 09:04:20 +02:00
|
|
|
|
if (savestate && !try_lock_vdec_context_creation())
|
2022-07-04 15:02:17 +02:00
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to savestate: HLE VDEC (video decoder) context(s) exist."
|
|
|
|
|
|
"\nLLE libvdec.sprx by selecting it in Adavcned tab -> Firmware Libraries."
|
|
|
|
|
|
"\nYou need to close the game for to take effect."
|
|
|
|
|
|
"\nIf you cannot close the game due to losing important progress your best chance is to skip the current cutscenes if any are played and retry.");
|
2022-07-05 09:04:20 +02:00
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
return to_ar;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
g_tls_log_prefix = []()
|
|
|
|
|
|
{
|
|
|
|
|
|
return std::string();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
if (m_state.exchange(system_state::stopped) == system_state::stopped)
|
|
|
|
|
|
{
|
2022-05-04 21:12:22 +02:00
|
|
|
|
// Ensure clean state
|
2022-07-11 11:24:09 +02:00
|
|
|
|
m_ar.reset();
|
2022-05-04 21:12:22 +02:00
|
|
|
|
argv.clear();
|
|
|
|
|
|
envp.clear();
|
|
|
|
|
|
data.clear();
|
|
|
|
|
|
disc.clear();
|
|
|
|
|
|
klic.clear();
|
|
|
|
|
|
hdd1.clear();
|
2022-05-12 18:59:33 +02:00
|
|
|
|
init_mem_containers = nullptr;
|
2022-05-04 21:12:22 +02:00
|
|
|
|
m_config_path.clear();
|
|
|
|
|
|
m_config_mode = cfg_mode::custom;
|
2022-07-12 15:04:33 +02:00
|
|
|
|
read_used_savestate_versions();
|
2022-07-15 21:11:39 +02:00
|
|
|
|
return to_ar;
|
2015-07-04 21:23:10 +02:00
|
|
|
|
}
|
2013-07-03 18:17:16 +02:00
|
|
|
|
|
2021-06-08 18:08:23 +02:00
|
|
|
|
sys_log.notice("Stopping emulator...");
|
|
|
|
|
|
|
2021-09-05 13:12:08 +02:00
|
|
|
|
{
|
|
|
|
|
|
// Show visual feedback to the user in case that stopping takes a while.
|
|
|
|
|
|
// This needs to be done before actually stopping, because otherwise the necessary threads will be terminated before we can show an image.
|
|
|
|
|
|
if (auto progress_dialog = g_fxo->try_get<named_thread<progress_dialog_server>>(); progress_dialog && +g_progr)
|
|
|
|
|
|
{
|
|
|
|
|
|
// We are currently showing a progress dialog. Notify it that we are going to stop emulation.
|
|
|
|
|
|
g_system_progress_stopping = true;
|
|
|
|
|
|
std::this_thread::sleep_for(20ms); // Enough for one frame to be rendered
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-09 10:41:01 +01:00
|
|
|
|
named_thread stop_watchdog("Stop Watchdog", [&]()
|
|
|
|
|
|
{
|
2020-06-01 01:27:33 +02:00
|
|
|
|
for (uint i = 0; thread_ctrl::state() != thread_state::aborting;)
|
2020-03-09 10:41:01 +01:00
|
|
|
|
{
|
2020-03-10 20:58:59 +01:00
|
|
|
|
// We don't need accurate timekeeping, using clocks may interfere with debugging
|
2022-07-07 21:14:43 +02:00
|
|
|
|
if (i >= (savestate ? 2000 : 1000))
|
2020-03-09 10:41:01 +01:00
|
|
|
|
{
|
2020-03-10 20:58:59 +01:00
|
|
|
|
// Total amount of waiting: about 5s
|
2020-03-09 10:41:01 +01:00
|
|
|
|
report_fatal_error("Stopping emulator took too long."
|
|
|
|
|
|
"\nSome thread has probably deadlocked. Aborting.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-10 20:58:59 +01:00
|
|
|
|
thread_ctrl::wait_for(5'000);
|
2020-06-01 01:27:33 +02:00
|
|
|
|
|
|
|
|
|
|
if (!g_watchdog_hold_ctr)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Don't count if there are still uninterruptable threads like PPU LLVM workers
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
2020-03-09 10:41:01 +01:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2021-06-05 21:15:15 +02:00
|
|
|
|
// Signal threads
|
2022-02-15 19:46:26 +01:00
|
|
|
|
|
|
|
|
|
|
// Stop the replay thread "game" first
|
|
|
|
|
|
if (auto thr = g_fxo->try_get<named_thread<rsx::rsx_replay_thread>>())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("Stopping RSX replay thread...");
|
|
|
|
|
|
thr->state += cpu_flag::stop;
|
|
|
|
|
|
|
|
|
|
|
|
// Wait for a couple of seconds
|
|
|
|
|
|
for (int i = 0; *thr <= thread_state::aborting && i < 300; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::this_thread::sleep_for(10ms);
|
|
|
|
|
|
process_qt_events();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (*thr <= thread_state::aborting)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to stop RSX replay thread in time.");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.notice("RSX replay thread stopped");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-27 12:18:48 +02:00
|
|
|
|
if (auto rsx = g_fxo->try_get<rsx::thread>())
|
|
|
|
|
|
{
|
|
|
|
|
|
*static_cast<cpu_thread*>(rsx) = thread_state::aborting;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-08 22:12:40 +02:00
|
|
|
|
for (const auto& [type, data] : *g_fxo)
|
2021-06-05 21:15:15 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (type.stop)
|
|
|
|
|
|
{
|
2021-06-08 22:12:40 +02:00
|
|
|
|
type.stop(data, thread_state::aborting);
|
2021-06-05 21:15:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-06-27 10:43:48 +02:00
|
|
|
|
sys_log.notice("All emulation threads have been signaled.");
|
|
|
|
|
|
|
|
|
|
|
|
// Wait fot newly created cpu_thread to see that emulation has been stopped
|
|
|
|
|
|
id_manager::g_mutex.lock_unlock();
|
|
|
|
|
|
|
2021-06-08 18:08:23 +02:00
|
|
|
|
GetCallbacks().on_stop();
|
|
|
|
|
|
|
2021-06-05 21:15:15 +02:00
|
|
|
|
// Join threads
|
2021-06-08 22:12:40 +02:00
|
|
|
|
for (const auto& [type, data] : *g_fxo)
|
2021-06-05 21:15:15 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (type.stop)
|
|
|
|
|
|
{
|
2021-06-08 22:12:40 +02:00
|
|
|
|
type.stop(data, thread_state::finished);
|
2021-06-05 21:15:15 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
// Save it first for maximum timing accuracy
|
|
|
|
|
|
const u64 timestamp = get_timebased_time();
|
2021-06-05 21:15:15 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
stop_watchdog = thread_state::aborting;
|
2020-02-25 09:43:04 +01:00
|
|
|
|
|
|
|
|
|
|
sys_log.notice("All threads have been stopped.");
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (savestate)
|
|
|
|
|
|
{
|
2022-07-15 21:11:39 +02:00
|
|
|
|
to_ar = std::make_unique<utils::serial>();
|
2022-07-09 15:18:48 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
// Savestate thread
|
|
|
|
|
|
named_thread emu_state_cap_thread("Emu State Capture Thread", [&]()
|
|
|
|
|
|
{
|
|
|
|
|
|
g_tls_log_prefix = []()
|
|
|
|
|
|
{
|
|
|
|
|
|
return fmt::format("Emu State Capture Thread: '%s'", g_tls_serialize_name);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
auto& ar = *to_ar;
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
2022-07-11 16:08:34 +02:00
|
|
|
|
read_used_savestate_versions(); // Reset version data
|
|
|
|
|
|
USING_SERIALIZATION_VERSION(global_version);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
|
|
|
|
|
// Avoid duplicating TAR object memory because it can be very large
|
|
|
|
|
|
auto save_tar = [&](const std::string& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
ar(usz{}); // Reserve memory to be patched later with correct size
|
|
|
|
|
|
const usz old_size = ar.data.size();
|
|
|
|
|
|
ar.data = tar_object::save_directory(path, std::move(ar.data));
|
2022-07-05 13:12:21 +02:00
|
|
|
|
ar.seek_end();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
const usz tar_size = ar.data.size() - old_size;
|
|
|
|
|
|
std::memcpy(ar.data.data() + old_size - sizeof(usz), &tar_size, sizeof(usz));
|
|
|
|
|
|
sys_log.success("Saved the contents of directory '%s' (size=0x%x)", path, tar_size);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
auto save_hdd1 = [&]()
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string _path = vfs::get("/dev_hdd1");
|
|
|
|
|
|
std::string_view path = _path;
|
|
|
|
|
|
|
|
|
|
|
|
path = path.substr(0, path.find_last_not_of(fs::delim) + 1);
|
|
|
|
|
|
|
|
|
|
|
|
ar(std::string(path.substr(path.find_last_of(fs::delim) + 1)));
|
|
|
|
|
|
|
|
|
|
|
|
if (!_path.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!g_cfg.savestate.suspend_emu)
|
|
|
|
|
|
{
|
|
|
|
|
|
save_tar(_path);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ar(usz{});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
auto save_hdd0 = [&]()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!g_cfg.savestate.suspend_emu && g_cfg.savestate.save_disc_game_data)
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string path = vfs::get("/dev_hdd0/game/");
|
|
|
|
|
|
|
|
|
|
|
|
for (auto& entry : fs::dir(path))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (entry.is_directory && entry.name != "." && entry.name != "..")
|
|
|
|
|
|
{
|
|
|
|
|
|
if (auto res = psf::load(path + entry.name + "/PARAM.SFO"); res && /*!m_title_id.empty() &&*/ psf::get_string(res.sfo, "TITLE_ID") == m_title_id && psf::get_string(res.sfo, "CATEGORY") == "GD")
|
|
|
|
|
|
{
|
|
|
|
|
|
ar(entry.name);
|
|
|
|
|
|
save_tar(path + entry.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ar(std::string{});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ar("RPCS3SAV"_u64);
|
|
|
|
|
|
ar(std::endian::native == std::endian::little);
|
|
|
|
|
|
ar(g_cfg.savestate.state_inspection_mode.get());
|
2022-07-09 12:19:08 +02:00
|
|
|
|
ar(std::array<u8, 32>{}); // Reserved for future use
|
2022-07-04 15:02:17 +02:00
|
|
|
|
ar(usz{0}); // Offset of versioning data, to be overwritten at the end of saving
|
2022-07-22 18:23:23 +02:00
|
|
|
|
|
|
|
|
|
|
if (auto dir = vfs::get("/dev_bdvd/PS3_GAME"); fs::is_dir(dir) && !fs::is_file(fs::get_parent_dir(dir) + "/PS3_DISC.SFB"))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Fake /dev_bdvd/PS3_GAME detected, use HDD0 for m_path restoration
|
|
|
|
|
|
ensure(vfs::unmount("/dev_bdvd/PS3_GAME"));
|
|
|
|
|
|
ar(vfs::retrieve(m_path));
|
2022-08-05 03:28:23 +02:00
|
|
|
|
ar(vfs::retrieve(disc));
|
2022-07-22 18:23:23 +02:00
|
|
|
|
ensure(vfs::mount("/dev_bdvd/PS3_GAME", dir));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ar(vfs::retrieve(m_path));
|
2022-08-05 03:28:23 +02:00
|
|
|
|
ar(!m_title_id.empty() && !vfs::get("/dev_bdvd").empty() ? m_title_id : vfs::retrieve(disc));
|
2022-07-22 18:23:23 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
ar(klic.empty() ? std::array<u8, 16>{} : std::bit_cast<std::array<u8, 16>>(klic[0]));
|
2022-07-09 12:19:08 +02:00
|
|
|
|
ar(m_game_dir);
|
2022-07-04 15:02:17 +02:00
|
|
|
|
save_hdd1();
|
|
|
|
|
|
save_hdd0();
|
2022-07-09 12:19:08 +02:00
|
|
|
|
ar(std::array<u8, 32>{}); // Reserved for future use
|
2022-07-04 15:02:17 +02:00
|
|
|
|
vm::save(ar);
|
|
|
|
|
|
g_fxo->save(ar);
|
2022-07-09 12:19:08 +02:00
|
|
|
|
ar(std::array<u8, 32>{}); // Reserved for future use
|
2022-07-04 15:02:17 +02:00
|
|
|
|
ar(timestamp);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Join it
|
|
|
|
|
|
emu_state_cap_thread();
|
|
|
|
|
|
|
|
|
|
|
|
if (emu_state_cap_thread == thread_state::errored)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Saving savestate failed due to fatal error!");
|
2022-07-15 21:11:39 +02:00
|
|
|
|
to_ar.reset();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
savestate = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cpu_thread::cleanup();
|
|
|
|
|
|
|
|
|
|
|
|
initialize_timebased_time(0, true);
|
|
|
|
|
|
|
2017-02-06 19:36:46 +01:00
|
|
|
|
lv2_obj::cleanup();
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
g_fxo->reset();
|
|
|
|
|
|
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.notice("Objects cleared...");
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
2015-07-11 22:44:53 +02:00
|
|
|
|
vm::close();
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
2019-01-26 21:15:45 +01:00
|
|
|
|
jit_runtime::finalize();
|
2017-09-18 18:16:36 +02:00
|
|
|
|
|
2020-11-19 09:12:59 +01:00
|
|
|
|
perf_stat_base::report();
|
|
|
|
|
|
|
2020-11-12 03:52:22 +01:00
|
|
|
|
static u64 aw_refs = 0;
|
|
|
|
|
|
static u64 aw_colm = 0;
|
|
|
|
|
|
static u64 aw_colc = 0;
|
|
|
|
|
|
static u64 aw_used = 0;
|
|
|
|
|
|
|
|
|
|
|
|
aw_refs = 0;
|
|
|
|
|
|
aw_colm = 0;
|
|
|
|
|
|
aw_colc = 0;
|
|
|
|
|
|
aw_used = 0;
|
|
|
|
|
|
|
2021-03-05 20:05:37 +01:00
|
|
|
|
atomic_wait::parse_hashtable([](u64 /*id*/, u32 refs, u64 ptr, u32 maxc) -> bool
|
2020-11-12 03:52:22 +01:00
|
|
|
|
{
|
2020-11-26 05:35:25 +01:00
|
|
|
|
aw_refs += refs != 0;
|
2020-11-12 03:52:22 +01:00
|
|
|
|
aw_used += ptr != 0;
|
|
|
|
|
|
|
2020-11-26 05:35:25 +01:00
|
|
|
|
aw_colm = std::max<u64>(aw_colm, maxc);
|
|
|
|
|
|
aw_colc += maxc != 0;
|
2020-11-12 03:52:22 +01:00
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
sys_log.notice("Atomic wait hashtable stats: [in_use=%u, used=%u, max_collision_weight=%u, total_collisions=%u]", aw_refs, aw_used, aw_colm, aw_colc);
|
|
|
|
|
|
|
2021-02-25 12:37:31 +01:00
|
|
|
|
m_stop_ctr++;
|
|
|
|
|
|
m_stop_ctr.notify_all();
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
if (savestate)
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string path = fs::get_cache_dir() + "/savestates/" + (m_title_id.empty() ? m_path.substr(m_path.find_last_of(fs::delim) + 1) : m_title_id) + ".SAVESTAT";
|
|
|
|
|
|
|
|
|
|
|
|
fs::pending_file file(path);
|
|
|
|
|
|
|
|
|
|
|
|
// Identifer -> version
|
2022-07-11 16:08:34 +02:00
|
|
|
|
std::vector<std::pair<u16, u16>> used_serial = read_used_savestate_versions();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
auto& ar = *to_ar;
|
2022-07-05 13:12:21 +02:00
|
|
|
|
const usz pos = ar.seek_end();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
std::memcpy(&ar.data[10], &pos, 8);// Set offset
|
|
|
|
|
|
ar(used_serial);
|
|
|
|
|
|
|
|
|
|
|
|
if (!file.file || (file.file.write(ar.data), !file.commit()))
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Failed to write savestate to file! (path='%s', %s)", path, fs::g_tls_error);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.success("Saved savestate! path='%s'", path);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-12 15:04:33 +02:00
|
|
|
|
ar.set_reading_state();
|
2022-07-04 15:02:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Boot arg cleanup (preserved in the case restarting)
|
2017-09-18 18:16:36 +02:00
|
|
|
|
argv.clear();
|
|
|
|
|
|
envp.clear();
|
|
|
|
|
|
data.clear();
|
2017-10-31 22:23:09 +01:00
|
|
|
|
disc.clear();
|
2017-10-31 22:36:25 +01:00
|
|
|
|
klic.clear();
|
2019-11-08 21:24:13 +01:00
|
|
|
|
hdd1.clear();
|
2022-05-12 18:59:33 +02:00
|
|
|
|
init_mem_containers = nullptr;
|
2021-09-22 21:44:52 +02:00
|
|
|
|
m_config_path.clear();
|
2021-10-05 18:38:52 +02:00
|
|
|
|
m_config_mode = cfg_mode::custom;
|
2022-07-15 21:11:39 +02:00
|
|
|
|
m_ar.reset();
|
2022-07-12 15:04:33 +02:00
|
|
|
|
read_used_savestate_versions();
|
2017-11-24 09:00:47 +01:00
|
|
|
|
|
2020-07-03 17:12:58 +02:00
|
|
|
|
// Always Enable display sleep, not only if it was prevented.
|
|
|
|
|
|
enable_display_sleep();
|
2020-07-03 17:11:28 +02:00
|
|
|
|
|
2022-02-05 11:49:29 +01:00
|
|
|
|
if (allow_autoexit)
|
2020-07-03 17:11:28 +02:00
|
|
|
|
{
|
2022-07-15 21:11:39 +02:00
|
|
|
|
Quit(g_cfg.misc.autoexit.get());
|
2020-07-03 17:11:28 +02:00
|
|
|
|
}
|
2022-07-15 21:11:39 +02:00
|
|
|
|
|
|
|
|
|
|
return to_ar;
|
2022-02-05 11:49:29 +01:00
|
|
|
|
}
|
2020-07-03 17:11:28 +02:00
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
game_boot_result Emulator::Restart()
|
2022-02-05 11:49:29 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (m_state == system_state::stopped)
|
|
|
|
|
|
{
|
|
|
|
|
|
return game_boot_result::generic_error;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto save_args = std::make_tuple(argv, envp, data, disc, klic, hdd1, m_config_mode, m_config_mode);
|
|
|
|
|
|
|
2022-07-15 21:11:39 +02:00
|
|
|
|
GracefulShutdown(false, false);
|
2022-02-05 11:49:29 +01:00
|
|
|
|
|
|
|
|
|
|
std::tie(argv, envp, data, disc, klic, hdd1, m_config_mode, m_config_mode) = std::move(save_args);
|
|
|
|
|
|
|
|
|
|
|
|
// Reload with prior configs.
|
|
|
|
|
|
if (const auto error = Load(m_title_id); error != game_boot_result::no_errors)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Restart failed: %s", error);
|
|
|
|
|
|
return error;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return game_boot_result::no_errors;
|
2020-07-03 17:11:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-07-06 20:46:21 +02:00
|
|
|
|
bool Emulator::Quit(bool force_quit)
|
2020-07-03 17:11:28 +02:00
|
|
|
|
{
|
2020-07-06 20:46:21 +02:00
|
|
|
|
m_force_boot = false;
|
2020-07-03 17:11:28 +02:00
|
|
|
|
|
2020-12-18 12:40:25 +01:00
|
|
|
|
// The callback is only used if we actually quit RPCS3
|
|
|
|
|
|
const auto on_exit = []()
|
2020-12-18 11:37:14 +01:00
|
|
|
|
{
|
2021-03-06 21:10:35 +01:00
|
|
|
|
Emu.CleanUp();
|
2020-12-18 12:40:25 +01:00
|
|
|
|
};
|
2021-04-02 00:54:32 +02:00
|
|
|
|
|
|
|
|
|
|
if (GetCallbacks().try_to_quit)
|
|
|
|
|
|
{
|
|
|
|
|
|
return GetCallbacks().try_to_quit(force_quit, on_exit);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
on_exit();
|
|
|
|
|
|
return true;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-06 21:10:35 +01:00
|
|
|
|
void Emulator::CleanUp()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Deinitialize object manager to prevent any hanging objects at program exit
|
|
|
|
|
|
g_fxo->clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-02-14 01:08:02 +01:00
|
|
|
|
std::string Emulator::GetFormattedTitle(double fps) const
|
2020-02-12 21:52:11 +01:00
|
|
|
|
{
|
2020-02-14 01:08:02 +01:00
|
|
|
|
rpcs3::title_format_data title_data;
|
|
|
|
|
|
title_data.format = g_cfg.misc.title_format.to_string();
|
|
|
|
|
|
title_data.title = GetTitle();
|
|
|
|
|
|
title_data.title_id = GetTitleID();
|
|
|
|
|
|
title_data.renderer = g_cfg.video.renderer.to_string();
|
2020-07-30 23:37:39 +02:00
|
|
|
|
title_data.vulkan_adapter = g_cfg.video.vk.adapter.to_string();
|
2020-02-14 01:08:02 +01:00
|
|
|
|
title_data.fps = fps;
|
|
|
|
|
|
|
|
|
|
|
|
return rpcs3::get_formatted_title(title_data);
|
2020-02-12 21:52:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-19 09:12:57 +02:00
|
|
|
|
s32 error_code::error_report(s32 result, const char* fmt, const fmt_type_info* sup, const u64* args)
|
2016-08-16 17:46:24 +02:00
|
|
|
|
{
|
2020-12-18 08:39:54 +01:00
|
|
|
|
static thread_local std::unordered_map<std::string, usz> g_tls_error_stats;
|
2017-08-23 22:14:52 +02:00
|
|
|
|
static thread_local std::string g_tls_error_str;
|
2017-08-02 16:49:18 +02:00
|
|
|
|
|
2021-05-19 09:12:57 +02:00
|
|
|
|
if (!sup && !args)
|
2017-08-02 16:49:18 +02:00
|
|
|
|
{
|
2021-05-19 09:12:57 +02:00
|
|
|
|
if (!fmt)
|
2017-08-02 16:49:18 +02:00
|
|
|
|
{
|
2018-09-15 13:42:14 +02:00
|
|
|
|
// Report and clean error state
|
2017-08-23 22:14:52 +02:00
|
|
|
|
for (auto&& pair : g_tls_error_stats)
|
2017-08-02 16:49:18 +02:00
|
|
|
|
{
|
|
|
|
|
|
if (pair.second > 3)
|
|
|
|
|
|
{
|
2020-01-31 14:43:59 +01:00
|
|
|
|
sys_log.error("Stat: %s [x%u]", pair.first, pair.second);
|
2017-08-02 16:49:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2018-09-15 13:42:14 +02:00
|
|
|
|
|
|
|
|
|
|
g_tls_error_stats.clear();
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2017-08-02 16:49:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-24 14:35:01 +02:00
|
|
|
|
ensure(fmt);
|
|
|
|
|
|
|
2020-01-31 14:43:59 +01:00
|
|
|
|
logs::channel* channel = &sys_log;
|
2017-02-02 18:47:25 +01:00
|
|
|
|
const char* func = "Unknown function";
|
2016-08-16 17:46:24 +02:00
|
|
|
|
|
2021-05-20 06:00:22 +02:00
|
|
|
|
if (auto ppu = get_current_cpu_thread<ppu_thread>())
|
2016-08-16 17:46:24 +02:00
|
|
|
|
{
|
2021-05-20 06:00:22 +02:00
|
|
|
|
if (ppu->current_function)
|
2016-08-16 17:46:24 +02:00
|
|
|
|
{
|
2021-05-20 06:00:22 +02:00
|
|
|
|
func = ppu->current_function;
|
2016-08-16 17:46:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-08-02 16:49:18 +02:00
|
|
|
|
// Format log message (use preallocated buffer)
|
2017-08-23 22:14:52 +02:00
|
|
|
|
g_tls_error_str.clear();
|
2021-05-19 09:12:57 +02:00
|
|
|
|
fmt::append(g_tls_error_str, "'%s' failed with 0x%08x", func, result);
|
2022-04-24 14:17:00 +02:00
|
|
|
|
|
|
|
|
|
|
// Add spacer between error and fmt if necessary
|
|
|
|
|
|
if (fmt[0] != ' ')
|
|
|
|
|
|
g_tls_error_str += " : ";
|
|
|
|
|
|
|
2021-05-19 09:12:57 +02:00
|
|
|
|
fmt::raw_append(g_tls_error_str, fmt, sup, args);
|
2017-08-02 16:49:18 +02:00
|
|
|
|
|
|
|
|
|
|
// Update stats and check log threshold
|
|
|
|
|
|
|
2022-04-24 14:35:26 +02:00
|
|
|
|
if (g_log_all_errors) [[unlikely]]
|
2017-08-02 16:49:18 +02:00
|
|
|
|
{
|
2022-07-19 17:05:51 +02:00
|
|
|
|
if (!g_tls_error_stats.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Report and clean error state
|
|
|
|
|
|
error_report(0, nullptr, nullptr, nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-04-24 14:35:26 +02:00
|
|
|
|
channel->error("%s", g_tls_error_str);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
const auto stat = ++g_tls_error_stats[g_tls_error_str];
|
|
|
|
|
|
|
|
|
|
|
|
if (stat <= 3)
|
|
|
|
|
|
{
|
|
|
|
|
|
channel->error("%s [%u]", g_tls_error_str, stat);
|
|
|
|
|
|
}
|
2017-08-02 16:49:18 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-19 09:12:57 +02:00
|
|
|
|
return result;
|
2016-08-16 17:46:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-04-09 21:12:47 +02:00
|
|
|
|
void Emulator::ConfigurePPUCache() const
|
2020-05-30 01:17:34 +02:00
|
|
|
|
{
|
2021-03-02 12:59:19 +01:00
|
|
|
|
auto& _main = g_fxo->get<ppu_module>();
|
2020-05-30 01:17:34 +02:00
|
|
|
|
|
2021-04-21 22:12:21 +02:00
|
|
|
|
_main.cache = rpcs3::utils::get_cache_dir();
|
2020-05-30 01:17:34 +02:00
|
|
|
|
|
|
|
|
|
|
if (!m_title_id.empty() && m_cat != "1P")
|
|
|
|
|
|
{
|
2021-04-07 23:05:18 +02:00
|
|
|
|
_main.cache += GetTitleID();
|
2021-03-02 12:59:19 +01:00
|
|
|
|
_main.cache += '/';
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
|
fmt::append(_main.cache, "ppu-%s-%s/", fmt::base57(_main.sha1), _main.path.substr(_main.path.find_last_of('/') + 1));
|
2020-05-30 01:17:34 +02:00
|
|
|
|
|
2021-03-02 12:59:19 +01:00
|
|
|
|
if (!fs::create_path(_main.cache))
|
2020-05-30 01:17:34 +02:00
|
|
|
|
{
|
2021-03-02 12:59:19 +01:00
|
|
|
|
sys_log.error("Failed to create cache directory: %s (%s)", _main.cache, fs::g_tls_error);
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2021-03-02 12:59:19 +01:00
|
|
|
|
sys_log.notice("Cache: %s", _main.cache);
|
2020-05-30 01:17:34 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-01-30 16:18:10 +01:00
|
|
|
|
std::set<std::string> Emulator::GetGameDirs() const
|
|
|
|
|
|
{
|
|
|
|
|
|
std::set<std::string> dirs;
|
|
|
|
|
|
|
|
|
|
|
|
// Add boot directory.
|
|
|
|
|
|
// For installed titles and disc titles with updates this is usually /dev_hdd0/game/<title_id>/
|
|
|
|
|
|
// For disc titles without updates this is /dev_bdvd/PS3_GAME/
|
|
|
|
|
|
if (const std::string dir = vfs::get(GetDir()); !dir.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
dirs.insert(dir + '/');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add more paths for disc titles.
|
|
|
|
|
|
if (const std::string dev_bdvd = vfs::get("/dev_bdvd/PS3_GAME");
|
|
|
|
|
|
!dev_bdvd.empty() && !GetTitleID().empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Add the dev_bdvd dir if available. This is necessary for disc titles with installed updates.
|
|
|
|
|
|
dirs.insert(dev_bdvd + '/');
|
|
|
|
|
|
|
|
|
|
|
|
// Naive search for all matching game data dirs.
|
|
|
|
|
|
const std::string game_dir = vfs::get("/dev_hdd0/game/");
|
|
|
|
|
|
for (auto&& entry : fs::dir(game_dir))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (entry.is_directory && entry.name.starts_with(GetTitleID()))
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string sfo_dir = game_dir + entry.name + '/';
|
|
|
|
|
|
const fs::file sfo_file(sfo_dir + "PARAM.SFO");
|
|
|
|
|
|
if (!sfo_file)
|
|
|
|
|
|
{
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const psf::registry psf = psf::load_object(sfo_file);
|
|
|
|
|
|
const std::string title_id = std::string(psf::get_string(psf, "TITLE_ID", ""));
|
|
|
|
|
|
|
|
|
|
|
|
if (title_id == GetTitleID())
|
|
|
|
|
|
{
|
|
|
|
|
|
dirs.insert(sfo_dir);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return dirs;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-07-27 03:54:16 +02:00
|
|
|
|
bool Emulator::IsPathInsideDir(std::string_view path, std::string_view dir) const
|
|
|
|
|
|
{
|
2022-01-13 05:24:04 +01:00
|
|
|
|
const std::string dir_path = GetCallbacks().resolve_path(dir);
|
2021-09-16 11:50:30 +02:00
|
|
|
|
|
2022-01-13 05:24:04 +01:00
|
|
|
|
return !dir_path.empty() && (GetCallbacks().resolve_path(path) + '/').starts_with(dir_path + '/');
|
2021-07-27 03:54:16 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
2021-09-16 01:34:20 +02:00
|
|
|
|
const std::string& Emulator::GetFakeCat() const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_cat == "DG")
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string mount_point = vfs::get("/dev_bdvd");
|
|
|
|
|
|
|
|
|
|
|
|
if (mount_point.empty() || !IsPathInsideDir(m_path, mount_point))
|
|
|
|
|
|
{
|
|
|
|
|
|
static const std::string s_hg = "HG";
|
|
|
|
|
|
return s_hg;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return m_cat;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2022-06-04 11:41:35 +02:00
|
|
|
|
const std::string Emulator::GetSfoDir(bool prefer_disc_sfo) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (prefer_disc_sfo)
|
|
|
|
|
|
{
|
|
|
|
|
|
const std::string sfo_dir = vfs::get("/dev_bdvd/PS3_GAME");
|
|
|
|
|
|
|
|
|
|
|
|
if (!sfo_dir.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
return sfo_dir;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return m_sfo_dir;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-21 22:13:22 +02:00
|
|
|
|
void Emulator::GetBdvdDir(std::string& bdvd_dir, std::string& sfb_dir, std::string& game_dir, const std::string& elf_dir)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Find disc directory by searching a valid PS3_DISC.SFB closest to root directory
|
|
|
|
|
|
std::string main_dir;
|
|
|
|
|
|
std::string_view main_dir_name;
|
|
|
|
|
|
|
|
|
|
|
|
for (std::string search_dir = elf_dir;;)
|
|
|
|
|
|
{
|
|
|
|
|
|
std::string parent_dir = fs::get_parent_dir(search_dir);
|
|
|
|
|
|
|
|
|
|
|
|
if (parent_dir.size() == search_dir.size())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Keep looking until root directory is reached
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (fs::file sfb_file{parent_dir + "/PS3_DISC.SFB", fs::read + fs::isfile}; sfb_file && sfb_file.size() >= 4 && sfb_file.read<u32>() == ".SFB"_u32)
|
|
|
|
|
|
{
|
|
|
|
|
|
main_dir_name = std::string_view{search_dir}.substr(search_dir.find_last_of(fs::delim) + 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (main_dir_name == "PS3_GAME" || std::regex_match(main_dir_name.begin(), main_dir_name.end(), std::regex("^PS3_GM[[:digit:]]{2}$")))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Remember valid disc directory
|
|
|
|
|
|
main_dir = search_dir;
|
|
|
|
|
|
sfb_dir = parent_dir;
|
|
|
|
|
|
main_dir_name = std::string_view{main_dir}.substr(main_dir.find_last_of(fs::delim) + 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
search_dir = std::move(parent_dir);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!sfb_dir.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
bdvd_dir = sfb_dir + "/";
|
|
|
|
|
|
game_dir = std::string{main_dir_name};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Emulator::EjectDisc()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Emu.IsRunning())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Can not eject disc if the Emulator is not running!");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-06-24 18:20:53 +02:00
|
|
|
|
if (vfs::get("/dev_bdvd").empty() && vfs::get("/dev_ps2disc").empty())
|
2022-06-21 22:13:22 +02:00
|
|
|
|
{
|
2022-06-24 18:20:53 +02:00
|
|
|
|
sys_log.error("Can not eject disc if both dev_bdvd and dev_ps2disc are not mounted!");
|
2022-06-21 22:13:22 +02:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sys_log.notice("Ejecting disc...");
|
|
|
|
|
|
|
|
|
|
|
|
m_sfo_dir.clear();
|
|
|
|
|
|
|
|
|
|
|
|
if (g_fxo->is_init<disc_change_manager>())
|
|
|
|
|
|
{
|
|
|
|
|
|
g_fxo->get<disc_change_manager>().eject_disc();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
game_boot_result Emulator::InsertDisc(const std::string& path)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!Emu.IsRunning())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Can not insert disc if the Emulator is not running!");
|
|
|
|
|
|
return game_boot_result::generic_error;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sys_log.notice("Inserting disc... (path='%s')", path);
|
|
|
|
|
|
|
|
|
|
|
|
const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
|
|
|
|
|
|
const bool from_hdd0_game = IsPathInsideDir(path, hdd0_game);
|
|
|
|
|
|
|
|
|
|
|
|
if (from_hdd0_game)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Inserting disc failed: Can not mount discs from '/dev_hdd0/game/'. (path='%s')", path);
|
|
|
|
|
|
return game_boot_result::wrong_disc_location;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string disc_root;
|
|
|
|
|
|
std::string ps3_game_dir;
|
|
|
|
|
|
const disc::disc_type disc_type = disc::get_disc_type(path, disc_root, ps3_game_dir);
|
|
|
|
|
|
|
|
|
|
|
|
if (disc_type == disc::disc_type::invalid)
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Inserting disc failed: not a disc (path='%s')", path);
|
|
|
|
|
|
return game_boot_result::wrong_disc_location;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ensure(!disc_root.empty());
|
|
|
|
|
|
|
|
|
|
|
|
u32 type = CELL_GAME_DISCTYPE_OTHER;
|
|
|
|
|
|
std::string title_id;
|
|
|
|
|
|
|
|
|
|
|
|
if (disc_type == disc::disc_type::ps3)
|
|
|
|
|
|
{
|
|
|
|
|
|
type = CELL_GAME_DISCTYPE_PS3;
|
|
|
|
|
|
|
|
|
|
|
|
// Double check PARAM.SFO
|
|
|
|
|
|
const std::string sfo_dir = rpcs3::utils::get_sfo_dir_from_game_path(disc_root);
|
|
|
|
|
|
const psf::registry _psf = psf::load_object(fs::file(sfo_dir + "/PARAM.SFO"));
|
|
|
|
|
|
|
|
|
|
|
|
if (_psf.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Inserting disc failed: Corrupted PARAM.SFO found! (path='%s/PARAM.SFO')", sfo_dir);
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
title_id = std::string(psf::get_string(_psf, "TITLE_ID"));
|
|
|
|
|
|
|
|
|
|
|
|
if (title_id.empty())
|
|
|
|
|
|
{
|
|
|
|
|
|
sys_log.error("Inserting disc failed: Corrupted PARAM.SFO found! TITLE_ID empty (path='%s/PARAM.SFO')", sfo_dir);
|
|
|
|
|
|
return game_boot_result::invalid_file_or_folder;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_sfo_dir = sfo_dir;
|
|
|
|
|
|
m_game_dir = ps3_game_dir;
|
|
|
|
|
|
|
|
|
|
|
|
sys_log.notice("New sfo dir: %s", m_sfo_dir);
|
|
|
|
|
|
sys_log.notice("New game dir: %s", m_game_dir);
|
|
|
|
|
|
|
|
|
|
|
|
ensure(vfs::mount("/dev_bdvd", disc_root));
|
|
|
|
|
|
ensure(vfs::mount("/dev_bdvd/PS3_GAME", disc_root + m_game_dir + "/"));
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (disc_type == disc::disc_type::ps2)
|
|
|
|
|
|
{
|
|
|
|
|
|
type = CELL_GAME_DISCTYPE_PS2;
|
|
|
|
|
|
|
|
|
|
|
|
ensure(vfs::mount("/dev_ps2disc", disc_root));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// TODO: find out where other discs are mounted
|
|
|
|
|
|
sys_log.todo("Mounting non-ps2/ps3 disc in dev_bdvd. Is this correct? (path='%s')", disc_root);
|
|
|
|
|
|
ensure(vfs::mount("/dev_bdvd", disc_root));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (g_fxo->is_init<disc_change_manager>())
|
|
|
|
|
|
{
|
|
|
|
|
|
g_fxo->get<disc_change_manager>().insert_disc(type, std::move(title_id));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return game_boot_result::no_errors;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-07-04 15:02:17 +02:00
|
|
|
|
utils::serial* Emulator::DeserialManager() const
|
|
|
|
|
|
{
|
|
|
|
|
|
ensure(!m_ar || !m_ar->is_writing());
|
|
|
|
|
|
return m_ar.get();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
|
Emulator Emu;
|