mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-12-27 06:21:02 +00:00
Add savestate buttons to home menu
This commit is contained in:
parent
a6313fa46c
commit
79d09d02ed
@ -42,6 +42,8 @@ public:
|
||||
// Underlying type
|
||||
using under = std::underlying_type_t<T>;
|
||||
|
||||
ENABLE_BITWISE_SERIALIZATION;
|
||||
|
||||
private:
|
||||
// Underlying value
|
||||
under m_data;
|
||||
@ -49,7 +51,7 @@ private:
|
||||
friend class atomic_bs_t<T>;
|
||||
|
||||
// Value constructor
|
||||
constexpr explicit bs_t(int, under data)
|
||||
constexpr explicit bs_t(int, under data) noexcept
|
||||
: m_data(data)
|
||||
{
|
||||
}
|
||||
@ -71,19 +73,19 @@ public:
|
||||
bs_t() = default;
|
||||
|
||||
// Construct from a single bit
|
||||
constexpr bs_t(T bit)
|
||||
constexpr bs_t(T bit) noexcept
|
||||
: m_data(shift(bit))
|
||||
{
|
||||
}
|
||||
|
||||
// Test for empty bitset
|
||||
constexpr explicit operator bool() const
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return m_data != 0;
|
||||
}
|
||||
|
||||
// Extract underlying data
|
||||
constexpr explicit operator under() const
|
||||
constexpr explicit operator under() const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
@ -138,7 +140,7 @@ public:
|
||||
return bs_t(0, lhs.m_data ^ rhs.m_data);
|
||||
}
|
||||
|
||||
constexpr bool operator ==(bs_t rhs) const
|
||||
constexpr bool operator ==(bs_t rhs) const noexcept
|
||||
{
|
||||
return m_data == rhs.m_data;
|
||||
}
|
||||
|
@ -163,6 +163,13 @@ extern u64 get_sysutil_cb_manager_read_count()
|
||||
|
||||
extern bool send_open_home_menu_cmds()
|
||||
{
|
||||
auto status = g_fxo->try_get<SysutilMenuOpenStatus>();
|
||||
|
||||
if (!status || status->active)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: handle CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE
|
||||
if (sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_BEGIN, 0) < 0 ||
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_SYSTEM_MENU_OPEN, 0) < 0 ||
|
||||
@ -171,15 +178,25 @@ extern bool send_open_home_menu_cmds()
|
||||
return false;
|
||||
}
|
||||
|
||||
status->active = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void send_close_home_menu_cmds()
|
||||
{
|
||||
auto status = g_fxo->try_get<SysutilMenuOpenStatus>();
|
||||
|
||||
if (!status || !status->active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: handle CELL_SYSUTIL_BGMPLAYBACK_STATUS_DISABLE
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_BGMPLAYBACK_STOP, 0);
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_SYSTEM_MENU_CLOSE, 0);
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_DRAWING_END, 0);
|
||||
|
||||
status->active = false;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -317,6 +317,14 @@ struct CellSysCacheParam
|
||||
vm::bptr<void> reserved;
|
||||
};
|
||||
|
||||
template <u32 BaseEvent>
|
||||
struct SysutilEventStatus
|
||||
{
|
||||
atomic_t<bool> active = false;
|
||||
};
|
||||
|
||||
using SysutilMenuOpenStatus = SysutilEventStatus<CELL_SYSUTIL_SYSTEM_MENU_OPEN>;
|
||||
|
||||
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
|
||||
extern s32 sysutil_send_system_cmd(u64 status, u64 param);
|
||||
s32 sysutil_check_name_string(const char* src, s32 minlen, s32 maxlen);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
extern atomic_t<bool> g_user_asked_for_recording;
|
||||
extern atomic_t<bool> g_user_asked_for_screenshot;
|
||||
extern bool boot_last_savestate(bool testing);
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
@ -39,6 +40,46 @@ namespace rsx
|
||||
return page_navigation::exit;
|
||||
});
|
||||
|
||||
const bool suspend_mode = g_cfg.savestate.suspend_emu.get();
|
||||
|
||||
std::unique_ptr<overlay_element> save_state = std::make_unique<home_menu_entry>(get_localized_string(suspend_mode ? localized_string_id::HOME_MENU_SAVESTATE_AND_EXIT : localized_string_id::HOME_MENU_SAVESTATE));
|
||||
add_item(save_state, [suspend_mode](pad_button btn) -> page_navigation
|
||||
{
|
||||
if (btn != pad_button::cross) return page_navigation::stay;
|
||||
|
||||
rsx_log.notice("User selected savestate in home menu");
|
||||
|
||||
Emu.CallFromMainThread([suspend_mode]()
|
||||
{
|
||||
Emu.Kill(false, true);
|
||||
|
||||
if (!suspend_mode)
|
||||
{
|
||||
Emu.Restart();
|
||||
}
|
||||
});
|
||||
|
||||
return page_navigation::exit;
|
||||
});
|
||||
|
||||
if (!suspend_mode && boot_last_savestate(true))
|
||||
{
|
||||
std::unique_ptr<overlay_element> reload_state = std::make_unique<home_menu_entry>(get_localized_string(localized_string_id::HOME_MENU_RELOAD_SAVESTATE));
|
||||
add_item(reload_state, [](pad_button btn) -> page_navigation
|
||||
{
|
||||
if (btn != pad_button::cross) return page_navigation::stay;
|
||||
|
||||
rsx_log.notice("User selected reload savestate in home menu");
|
||||
|
||||
Emu.CallFromMainThread([]()
|
||||
{
|
||||
boot_last_savestate(false);
|
||||
});
|
||||
|
||||
return page_navigation::exit;
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<overlay_element> recording = std::make_unique<home_menu_entry>(get_localized_string(localized_string_id::HOME_MENU_RECORDING));
|
||||
add_item(recording, [](pad_button btn) -> page_navigation
|
||||
{
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "Emu/Cell/lv2/sys_overlay.h"
|
||||
#include "Emu/Cell/lv2/sys_spu.h"
|
||||
#include "Emu/Cell/Modules/cellGame.h"
|
||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||
|
||||
#include "Emu/title.h"
|
||||
#include "Emu/IdManager.h"
|
||||
@ -84,6 +85,8 @@ extern bool is_savestate_version_compatible(const std::vector<std::pair<u16, u16
|
||||
extern std::vector<std::pair<u16, u16>> read_used_savestate_versions();
|
||||
std::string get_savestate_path(std::string_view title_id, std::string_view boot_path);
|
||||
|
||||
extern void send_close_home_menu_cmds();
|
||||
|
||||
fs::file g_tty;
|
||||
atomic_t<s64> g_tty_size{0};
|
||||
std::array<std::deque<std::string>, 16> g_tty_input;
|
||||
@ -206,7 +209,12 @@ void init_fxo_for_exec(utils::serial* ar, bool full = false)
|
||||
if (ar)
|
||||
{
|
||||
Emu.ExecDeserializationRemnants();
|
||||
ar->pos += 32; // Reserved area
|
||||
|
||||
auto flags = (*ar)(Emu.m_savestate_extension_flags1);
|
||||
|
||||
const usz advance = (Emu.m_savestate_extension_flags1 & Emulator::SaveStateExtentionFlags1::SupportsMenuOpenResume ? 32 : 31);
|
||||
|
||||
ar->pos += advance; // Reserved area
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,6 +896,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||
}
|
||||
|
||||
m_state_inspection_savestate = g_cfg.savestate.state_inspection_mode.get();
|
||||
m_savestate_extension_flags1 = {};
|
||||
|
||||
bool resolve_path_as_vfs_path = false;
|
||||
|
||||
@ -2248,11 +2257,29 @@ void Emulator::FinalizeRunRequest()
|
||||
spu.state.notify_one(cpu_flag::stop);
|
||||
};
|
||||
|
||||
if (m_savestate_extension_flags1 & SaveStateExtentionFlags1::ShouldCloseMenu)
|
||||
{
|
||||
g_fxo->get<SysutilMenuOpenStatus>().active = true;
|
||||
}
|
||||
|
||||
idm::select<named_thread<spu_thread>>(on_select);
|
||||
|
||||
lv2_obj::make_scheduler_ready();
|
||||
|
||||
m_state.compare_and_swap_test(system_state::starting, system_state::running);
|
||||
|
||||
if (m_savestate_extension_flags1 & SaveStateExtentionFlags1::ShouldCloseMenu)
|
||||
{
|
||||
std::thread([this, info = ProcureCurrentEmulationCourseInformation()]()
|
||||
{
|
||||
std::this_thread::sleep_for(2s);
|
||||
|
||||
CallFromMainThread([this]()
|
||||
{
|
||||
send_close_home_menu_cmds();
|
||||
}, info);
|
||||
}).detach();
|
||||
}
|
||||
}
|
||||
|
||||
bool Emulator::Pause(bool freeze_emulation, bool show_resume_message)
|
||||
@ -2579,6 +2606,7 @@ std::shared_ptr<utils::serial> Emulator::Kill(bool allow_autoexit, bool savestat
|
||||
m_config_path.clear();
|
||||
m_config_mode = cfg_mode::custom;
|
||||
read_used_savestate_versions();
|
||||
m_savestate_extension_flags1 = {};
|
||||
return to_ar;
|
||||
}
|
||||
|
||||
@ -2755,6 +2783,16 @@ std::shared_ptr<utils::serial> Emulator::Kill(bool allow_autoexit, bool savestat
|
||||
ar(std::array<u8, 32>{}); // Reserved for future use
|
||||
vm::save(ar);
|
||||
g_fxo->save(ar);
|
||||
|
||||
bs_t<SaveStateExtentionFlags1> extension_flags{SaveStateExtentionFlags1::SupportsMenuOpenResume};
|
||||
|
||||
if (g_fxo->get<SysutilMenuOpenStatus>().active)
|
||||
{
|
||||
extension_flags += SaveStateExtentionFlags1::ShouldCloseMenu;
|
||||
}
|
||||
|
||||
ar(extension_flags);
|
||||
|
||||
ar(std::array<u8, 32>{}); // Reserved for future use
|
||||
ar(timestamp);
|
||||
});
|
||||
@ -2874,6 +2912,7 @@ std::shared_ptr<utils::serial> Emulator::Kill(bool allow_autoexit, bool savestat
|
||||
m_config_mode = cfg_mode::custom;
|
||||
m_ar.reset();
|
||||
read_used_savestate_versions();
|
||||
m_savestate_extension_flags1 = {};
|
||||
|
||||
// Always Enable display sleep, not only if it was prevented.
|
||||
enable_display_sleep();
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "util/types.hpp"
|
||||
#include "util/atomic.hpp"
|
||||
#include "Utilities/bit_set.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -158,6 +159,16 @@ class Emulator final
|
||||
}
|
||||
}
|
||||
|
||||
enum class SaveStateExtentionFlags1 : u8
|
||||
{
|
||||
SupportsMenuOpenResume,
|
||||
ShouldCloseMenu,
|
||||
|
||||
__bitset_enum_max,
|
||||
};
|
||||
|
||||
bs_t<SaveStateExtentionFlags1> m_savestate_extension_flags1{};
|
||||
|
||||
public:
|
||||
static constexpr std::string_view game_id_boot_prefix = "%RPCS3_GAMEID%:";
|
||||
static constexpr std::string_view vfs_boot_prefix = "%RPCS3_VFS%:";
|
||||
|
@ -167,6 +167,9 @@ enum class localized_string_id
|
||||
HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY,
|
||||
HOME_MENU_SETTINGS_DEBUG,
|
||||
HOME_MENU_SCREENSHOT,
|
||||
HOME_MENU_SAVESTATE,
|
||||
HOME_MENU_SAVESTATE_AND_EXIT,
|
||||
HOME_MENU_RELOAD_SAVESTATE,
|
||||
HOME_MENU_RECORDING,
|
||||
|
||||
EMULATION_PAUSED_RESUME_WITH_START,
|
||||
|
@ -174,7 +174,7 @@ std::vector<std::pair<u16, u16>> read_used_savestate_versions()
|
||||
return used_serial;
|
||||
}
|
||||
|
||||
bool boot_last_savestate()
|
||||
bool boot_last_savestate(bool testing)
|
||||
{
|
||||
if (!g_cfg.savestate.suspend_emu && !Emu.GetTitleID().empty() && (Emu.IsRunning() || Emu.GetStatus() == system_state::paused))
|
||||
{
|
||||
@ -203,7 +203,15 @@ bool boot_last_savestate()
|
||||
}
|
||||
}
|
||||
|
||||
if (fs::is_file(savestate_path))
|
||||
const bool result = fs::is_file(savestate_path);
|
||||
|
||||
if (testing)
|
||||
{
|
||||
sys_log.trace("boot_last_savestate(true) returned %s.", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
sys_log.success("Booting the most recent savestate \'%s\' using the Reload shortcut.", savestate_path);
|
||||
Emu.GracefulShutdown(false);
|
||||
|
@ -372,8 +372,8 @@ void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKey
|
||||
return;
|
||||
}
|
||||
|
||||
extern bool boot_last_savestate();
|
||||
boot_last_savestate();
|
||||
extern bool boot_last_savestate(bool testing);
|
||||
boot_last_savestate(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -186,6 +186,9 @@ private:
|
||||
case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY: return tr("Performance Overlay");
|
||||
case localized_string_id::HOME_MENU_SETTINGS_DEBUG: return tr("Debug");
|
||||
case localized_string_id::HOME_MENU_SCREENSHOT: return tr("Take Screenshot");
|
||||
case localized_string_id::HOME_MENU_SAVESTATE: return tr("Save Emulation State");
|
||||
case localized_string_id::HOME_MENU_SAVESTATE_AND_EXIT: return tr("Save Emulation State And Exit");
|
||||
case localized_string_id::HOME_MENU_RELOAD_SAVESTATE: return tr("Reload Last Emulation State");
|
||||
case localized_string_id::HOME_MENU_RECORDING: return tr("Start/Stop Recording");
|
||||
case localized_string_id::EMULATION_PAUSED_RESUME_WITH_START: return tr("Press and hold the START button to resume");
|
||||
case localized_string_id::EMULATION_RESUMING: return tr("Resuming...!");
|
||||
|
Loading…
Reference in New Issue
Block a user