mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
overlays: add simple home menu
This commit is contained in:
parent
ac2b2d82d2
commit
44771150b7
@ -442,6 +442,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||
RSX/Overlays/overlay_cursor.cpp
|
||||
RSX/Overlays/overlay_edit_text.cpp
|
||||
RSX/Overlays/overlay_fonts.cpp
|
||||
RSX/Overlays/overlay_home_menu.cpp
|
||||
RSX/Overlays/overlay_list_view.cpp
|
||||
RSX/Overlays/overlay_media_list_dialog.cpp
|
||||
RSX/Overlays/overlay_message.cpp
|
||||
|
@ -161,6 +161,27 @@ extern u64 get_sysutil_cb_manager_read_count()
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern bool send_open_home_menu_cmds()
|
||||
{
|
||||
// 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 ||
|
||||
sysutil_send_system_cmd(CELL_SYSUTIL_BGMPLAYBACK_PLAY, 0) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern void send_close_home_menu_cmds()
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
template <>
|
||||
void fmt_class_string<CellSysutilLang>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
LOG_CHANNEL(screenshot_log, "SCREENSHOT");
|
||||
|
||||
extern atomic_t<bool> g_user_asked_for_screenshot;
|
||||
extern atomic_t<recording_mode> g_recording_mode;
|
||||
|
||||
namespace gl
|
||||
@ -235,7 +236,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
|
||||
if (image_to_flip)
|
||||
{
|
||||
if (m_frame->screenshot_toggle || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame()))
|
||||
if (g_user_asked_for_screenshot || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame()))
|
||||
{
|
||||
std::vector<u8> sshot_frame(buffer_height * buffer_width * 4);
|
||||
|
||||
@ -251,9 +252,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
{
|
||||
screenshot_log.error("Failed to capture image: 0x%x", err);
|
||||
}
|
||||
else if (m_frame->screenshot_toggle)
|
||||
else if (g_user_asked_for_screenshot.exchange(false))
|
||||
{
|
||||
m_frame->screenshot_toggle = false;
|
||||
m_frame->take_screenshot(std::move(sshot_frame), buffer_width, buffer_height, false);
|
||||
}
|
||||
else
|
||||
|
@ -29,7 +29,6 @@ public:
|
||||
|
||||
virtual display_handle_t handle() const = 0;
|
||||
|
||||
atomic_t<bool> screenshot_toggle = false;
|
||||
virtual bool can_consume_frame() const = 0;
|
||||
virtual void present_frame(std::vector<u8>& data, const u32 width, const u32 height, bool is_bgra) const = 0;
|
||||
virtual void take_screenshot(const std::vector<u8> sshot_data, const u32 sshot_width, const u32 sshot_height, bool is_bgra) = 0;
|
||||
|
268
rpcs3/Emu/RSX/Overlays/overlay_home_menu.cpp
Normal file
268
rpcs3/Emu/RSX/Overlays/overlay_home_menu.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
#include "stdafx.h"
|
||||
#include "overlay_home_menu.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
|
||||
extern atomic_t<bool> g_user_asked_for_recording;
|
||||
extern atomic_t<bool> g_user_asked_for_screenshot;
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
home_menu_dialog::home_menu_entry::home_menu_entry(const std::string& text)
|
||||
{
|
||||
std::unique_ptr<overlay_element> text_stack = std::make_unique<vertical_layout>();
|
||||
std::unique_ptr<overlay_element> padding = std::make_unique<spacer>();
|
||||
std::unique_ptr<overlay_element> header_text = std::make_unique<label>(text);
|
||||
|
||||
padding->set_size(1, 1);
|
||||
header_text->set_size(1240, height);
|
||||
header_text->set_font("Arial", 16);
|
||||
header_text->set_wrap_text(true);
|
||||
header_text->align_text(text_align::center);
|
||||
|
||||
// Make back color transparent for text
|
||||
header_text->back_color.a = 0.f;
|
||||
|
||||
static_cast<vertical_layout*>(text_stack.get())->pack_padding = 5;
|
||||
static_cast<vertical_layout*>(text_stack.get())->add_element(padding);
|
||||
static_cast<vertical_layout*>(text_stack.get())->add_element(header_text);
|
||||
|
||||
// Pack
|
||||
this->pack_padding = 15;
|
||||
add_element(text_stack);
|
||||
}
|
||||
|
||||
home_menu_dialog::home_menu_dialog()
|
||||
{
|
||||
m_allow_input_on_pause = true;
|
||||
|
||||
m_dim_background = std::make_unique<overlay_element>();
|
||||
m_dim_background->set_size(1280, 720);
|
||||
m_dim_background->back_color.a = 0.5f;
|
||||
|
||||
m_list = std::make_unique<list_view>(1240, 540, false);
|
||||
m_list->set_pos(20, 85);
|
||||
|
||||
m_description = std::make_unique<label>();
|
||||
m_description->set_font("Arial", 20);
|
||||
m_description->set_pos(20, 37);
|
||||
m_description->set_text(get_localized_string(localized_string_id::HOME_MENU_TITLE));
|
||||
m_description->auto_resize();
|
||||
m_description->back_color.a = 0.f;
|
||||
|
||||
fade_animation.duration = 0.15f;
|
||||
|
||||
return_code = selection_code::canceled;
|
||||
}
|
||||
|
||||
void home_menu_dialog::update()
|
||||
{
|
||||
static u64 frame = 0;
|
||||
|
||||
if (Emu.IsPaused())
|
||||
{
|
||||
// Let's keep updating the animation anyway
|
||||
frame++;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame = rsx::get_current_renderer()->vblank_count;
|
||||
}
|
||||
|
||||
if (fade_animation.active)
|
||||
{
|
||||
fade_animation.update(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void home_menu_dialog::on_button_pressed(pad_button button_press)
|
||||
{
|
||||
if (fade_animation.active) return;
|
||||
|
||||
bool close_dialog = false;
|
||||
|
||||
switch (button_press)
|
||||
{
|
||||
case pad_button::cross:
|
||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
||||
|
||||
if (const usz index = static_cast<usz>(m_list->get_selected_index()); index < m_callbacks.size())
|
||||
{
|
||||
if (const std::function<bool()>& func = ::at32(m_callbacks, index))
|
||||
{
|
||||
close_dialog = func();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case pad_button::circle:
|
||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
||||
close_dialog = true;
|
||||
break;
|
||||
case pad_button::dpad_up:
|
||||
case pad_button::ls_up:
|
||||
m_list->select_previous();
|
||||
break;
|
||||
case pad_button::dpad_down:
|
||||
case pad_button::ls_down:
|
||||
m_list->select_next();
|
||||
break;
|
||||
case pad_button::L1:
|
||||
m_list->select_previous(10);
|
||||
break;
|
||||
case pad_button::R1:
|
||||
m_list->select_next(10);
|
||||
break;
|
||||
default:
|
||||
rsx_log.trace("[ui] Button %d pressed", static_cast<u8>(button_press));
|
||||
break;
|
||||
}
|
||||
|
||||
if (close_dialog)
|
||||
{
|
||||
fade_animation.current = color4f(1.f);
|
||||
fade_animation.end = color4f(0.f);
|
||||
fade_animation.active = true;
|
||||
|
||||
fade_animation.on_finish = [this]
|
||||
{
|
||||
close(true, true);
|
||||
|
||||
if (g_cfg.misc.pause_during_home_menu)
|
||||
{
|
||||
Emu.BlockingCallFromMainThread([]()
|
||||
{
|
||||
Emu.Resume();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
||||
}
|
||||
}
|
||||
|
||||
compiled_resource home_menu_dialog::get_compiled()
|
||||
{
|
||||
if (!visible)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
compiled_resource result;
|
||||
result.add(m_dim_background->get_compiled());
|
||||
result.add(m_list->get_compiled());
|
||||
result.add(m_description->get_compiled());
|
||||
|
||||
fade_animation.apply(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct home_menu_dialog_thread
|
||||
{
|
||||
static constexpr auto thread_name = "Home Menu Thread"sv;
|
||||
};
|
||||
|
||||
void home_menu_dialog::add_item(const std::string& text, std::function<bool()> callback)
|
||||
{
|
||||
m_callbacks.push_back(std::move(callback));
|
||||
m_entries.push_back(std::make_unique<home_menu_entry>(text));
|
||||
}
|
||||
|
||||
error_code home_menu_dialog::show(std::function<void(s32 status)> on_close)
|
||||
{
|
||||
visible = false;
|
||||
|
||||
add_item(get_localized_string(localized_string_id::HOME_MENU_RESUME), []() -> bool
|
||||
{
|
||||
rsx_log.notice("User selected resume in home menu");
|
||||
return true;
|
||||
});
|
||||
|
||||
add_item(get_localized_string(localized_string_id::HOME_MENU_SCREENSHOT), []() -> bool
|
||||
{
|
||||
rsx_log.notice("User selected screenshot in home menu");
|
||||
g_user_asked_for_screenshot = true;
|
||||
return true;
|
||||
});
|
||||
|
||||
add_item(get_localized_string(localized_string_id::HOME_MENU_RECORDING), []() -> bool
|
||||
{
|
||||
rsx_log.notice("User selected recording in home menu");
|
||||
g_user_asked_for_recording = true;
|
||||
return true;
|
||||
});
|
||||
|
||||
add_item(get_localized_string(localized_string_id::HOME_MENU_EXIT_GAME), []() -> bool
|
||||
{
|
||||
rsx_log.notice("User selected exit game in home menu");
|
||||
Emu.CallFromMainThread([]
|
||||
{
|
||||
Emu.GracefulShutdown(false, true);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
// Center vertically if necessary
|
||||
if (const usz total_height = home_menu_entry::height * m_entries.size(); total_height < m_list->h)
|
||||
{
|
||||
m_list->advance_pos = (m_list->h - total_height) / 2;
|
||||
}
|
||||
|
||||
for (auto& entry : m_entries)
|
||||
{
|
||||
m_list->add_entry(entry);
|
||||
}
|
||||
|
||||
fade_animation.current = color4f(0.f);
|
||||
fade_animation.end = color4f(1.f);
|
||||
fade_animation.active = true;
|
||||
|
||||
this->on_close = std::move(on_close);
|
||||
visible = true;
|
||||
|
||||
auto& list_thread = g_fxo->get<named_thread<home_menu_dialog_thread>>();
|
||||
|
||||
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
||||
|
||||
list_thread([&, notify]()
|
||||
{
|
||||
const u64 tbit = alloc_thread_bit();
|
||||
g_thread_bit = tbit;
|
||||
|
||||
*notify = true;
|
||||
notify->notify_one();
|
||||
|
||||
auto ref = g_fxo->get<display_manager>().get(uid);
|
||||
|
||||
if (const auto error = run_input_loop())
|
||||
{
|
||||
if (error != selection_code::canceled)
|
||||
{
|
||||
rsx_log.error("Home menu dialog input loop exited with error code=%d", error);
|
||||
}
|
||||
}
|
||||
|
||||
thread_bits &= ~tbit;
|
||||
thread_bits.notify_all();
|
||||
});
|
||||
|
||||
if (g_cfg.misc.pause_during_home_menu)
|
||||
{
|
||||
Emu.BlockingCallFromMainThread([]()
|
||||
{
|
||||
Emu.Pause(false, false);
|
||||
});
|
||||
}
|
||||
|
||||
while (list_thread < thread_state::errored && !*notify)
|
||||
{
|
||||
notify->wait(false, atomic_wait_timeout{1'000'000});
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
} // namespace overlays
|
||||
} // namespace RSX
|
42
rpcs3/Emu/RSX/Overlays/overlay_home_menu.h
Normal file
42
rpcs3/Emu/RSX/Overlays/overlay_home_menu.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "overlays.h"
|
||||
#include "overlay_list_view.hpp"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
|
||||
namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
struct home_menu_dialog : public user_interface
|
||||
{
|
||||
private:
|
||||
struct home_menu_entry : horizontal_layout
|
||||
{
|
||||
public:
|
||||
home_menu_entry(const std::string& text);
|
||||
|
||||
static constexpr u16 height = 40;
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<overlay_element>> m_entries;
|
||||
std::vector<std::function<bool()>> m_callbacks;
|
||||
std::unique_ptr<overlay_element> m_dim_background;
|
||||
std::unique_ptr<list_view> m_list;
|
||||
std::unique_ptr<label> m_description;
|
||||
|
||||
animation_color_interpolate fade_animation;
|
||||
|
||||
public:
|
||||
home_menu_dialog();
|
||||
|
||||
void update() override;
|
||||
void on_button_pressed(pad_button button_press) override;
|
||||
|
||||
compiled_resource get_compiled() override;
|
||||
|
||||
void add_item(const std::string& text, std::function<bool()> callback);
|
||||
error_code show(std::function<void(s32 status)> on_close);
|
||||
};
|
||||
}
|
||||
}
|
@ -6,7 +6,8 @@ namespace rsx
|
||||
{
|
||||
namespace overlays
|
||||
{
|
||||
list_view::list_view(u16 width, u16 height)
|
||||
list_view::list_view(u16 width, u16 height, bool use_separators)
|
||||
: m_use_separators(use_separators)
|
||||
{
|
||||
w = width;
|
||||
h = height;
|
||||
@ -62,7 +63,7 @@ namespace rsx
|
||||
return; // Ideally unreachable but it should still be possible to recover by user interaction.
|
||||
}
|
||||
|
||||
const usz current_index = static_cast<usz>(m_selected_entry) * 2;
|
||||
const usz current_index = static_cast<usz>(m_selected_entry) * (m_use_separators ? 2 : 1);
|
||||
|
||||
if (m_items.size() <= current_index)
|
||||
{
|
||||
@ -139,11 +140,14 @@ namespace rsx
|
||||
m_elements_count++;
|
||||
|
||||
// Add separator
|
||||
auto separator = std::make_unique<overlay_element>();
|
||||
separator->back_color = fore_color;
|
||||
separator->w = w;
|
||||
separator->h = 2;
|
||||
add_element(separator);
|
||||
if (m_use_separators)
|
||||
{
|
||||
auto separator = std::make_unique<overlay_element>();
|
||||
separator->back_color = fore_color;
|
||||
separator->w = w;
|
||||
separator->h = 2;
|
||||
add_element(separator);
|
||||
}
|
||||
|
||||
if (m_selected_entry < 0)
|
||||
m_selected_entry = 0;
|
||||
@ -189,7 +193,7 @@ namespace rsx
|
||||
{
|
||||
if (!is_compiled)
|
||||
{
|
||||
auto compiled = vertical_layout::get_compiled();
|
||||
auto& compiled = vertical_layout::get_compiled();
|
||||
compiled.add(m_highlight_box->get_compiled());
|
||||
compiled.add(m_scroll_indicator_top->get_compiled());
|
||||
compiled.add(m_scroll_indicator_bottom->get_compiled());
|
||||
|
@ -17,10 +17,11 @@ namespace rsx
|
||||
s32 m_selected_entry = -1;
|
||||
u16 m_elements_count = 0;
|
||||
|
||||
bool m_use_separators = false;
|
||||
bool m_cancel_only = false;
|
||||
|
||||
public:
|
||||
list_view(u16 width, u16 height);
|
||||
list_view(u16 width, u16 height, bool use_separators = true);
|
||||
|
||||
void update_selection();
|
||||
|
||||
|
@ -126,7 +126,7 @@ namespace rsx
|
||||
return selection_code::canceled;
|
||||
}
|
||||
|
||||
if (Emu.IsPaused())
|
||||
if (Emu.IsPaused() && !m_allow_input_on_pause)
|
||||
{
|
||||
thread_ctrl::wait_for(10000);
|
||||
continue;
|
||||
|
@ -115,6 +115,7 @@ namespace rsx
|
||||
atomic_t<u64> thread_bits = 0;
|
||||
bool m_keyboard_input_enabled = false; // Allow keyboard events
|
||||
bool m_keyboard_pad_handler_active = true; // Initialized as true to prevent keyboard input until proven otherwise.
|
||||
bool m_allow_input_on_pause = false;
|
||||
|
||||
static thread_local u64 g_thread_bit;
|
||||
|
||||
|
@ -38,6 +38,8 @@ class GSRender;
|
||||
|
||||
#define CMD_DEBUG 0
|
||||
|
||||
atomic_t<bool> g_user_asked_for_recording = false;
|
||||
atomic_t<bool> g_user_asked_for_screenshot = false;
|
||||
atomic_t<bool> g_user_asked_for_frame_capture = false;
|
||||
atomic_t<bool> g_disable_frame_limit = false;
|
||||
rsx::frame_trace_data frame_debug;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "util/asm.hpp"
|
||||
#include "util/video_provider.h"
|
||||
|
||||
extern atomic_t<bool> g_user_asked_for_screenshot;
|
||||
extern atomic_t<recording_mode> g_recording_mode;
|
||||
|
||||
void VKGSRender::reinitialize_swapchain()
|
||||
@ -675,7 +676,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
m_upscaler->scale_output(*m_current_command_buffer, image_to_flip, target_image, target_layout, rgn, UPSCALE_AND_COMMIT | UPSCALE_DEFAULT_VIEW);
|
||||
}
|
||||
|
||||
if (m_frame->screenshot_toggle || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame()))
|
||||
if (g_user_asked_for_screenshot || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame()))
|
||||
{
|
||||
const usz sshot_size = buffer_height * buffer_width * 4;
|
||||
|
||||
@ -709,9 +710,8 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
|
||||
const bool is_bgra = image_to_flip->format() == VK_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
if (m_frame->screenshot_toggle)
|
||||
if (g_user_asked_for_screenshot.exchange(false))
|
||||
{
|
||||
m_frame->screenshot_toggle = false;
|
||||
m_frame->take_screenshot(std::move(sshot_frame), buffer_width, buffer_height, is_bgra);
|
||||
}
|
||||
else
|
||||
|
@ -2192,7 +2192,7 @@ void Emulator::FinalizeRunRequest()
|
||||
m_state.compare_and_swap_test(system_state::starting, system_state::running);
|
||||
}
|
||||
|
||||
bool Emulator::Pause(bool freeze_emulation)
|
||||
bool Emulator::Pause(bool freeze_emulation, bool show_resume_message)
|
||||
{
|
||||
const u64 start = get_system_time();
|
||||
|
||||
@ -2245,11 +2245,11 @@ bool Emulator::Pause(bool freeze_emulation)
|
||||
|
||||
GetCallbacks().on_pause();
|
||||
|
||||
BlockingCallFromMainThread([this]()
|
||||
BlockingCallFromMainThread([this, show_resume_message]()
|
||||
{
|
||||
const auto status = Emu.GetStatus(false);
|
||||
|
||||
if (status != system_state::paused && status != system_state::frozen)
|
||||
if (!show_resume_message || (status != system_state::paused && status != system_state::frozen))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ public:
|
||||
void FixGuestTime();
|
||||
void FinalizeRunRequest();
|
||||
|
||||
bool Pause(bool freeze_emulation = false);
|
||||
bool Pause(bool freeze_emulation = false, bool show_resume_message = true);
|
||||
void Resume();
|
||||
void GracefulShutdown(bool allow_autoexit = true, bool async_op = false, bool savestate = false);
|
||||
std::shared_ptr<utils::serial> Kill(bool allow_autoexit = true, bool savestate = false);
|
||||
|
@ -149,6 +149,12 @@ enum class localized_string_id
|
||||
RPCN_ERROR_UNKNOWN,
|
||||
RPCN_SUCCESS_LOGGED_ON,
|
||||
|
||||
HOME_MENU_TITLE,
|
||||
HOME_MENU_EXIT_GAME,
|
||||
HOME_MENU_RESUME,
|
||||
HOME_MENU_SCREENSHOT,
|
||||
HOME_MENU_RECORDING,
|
||||
|
||||
EMULATION_PAUSED_RESUME_WITH_START,
|
||||
EMULATION_RESUMING,
|
||||
EMULATION_FROZEN,
|
||||
|
@ -336,6 +336,7 @@ struct cfg_root : cfg::node
|
||||
cfg::string gdb_server{ this, "GDB Server", "127.0.0.1:2345" };
|
||||
cfg::_bool silence_all_logs{ this, "Silence All Logs", false, true };
|
||||
cfg::string title_format{ this, "Window Title Format", "FPS: %F | %R | %V | %T [%t]", true };
|
||||
cfg::_bool pause_during_home_menu{this, "Pause Emulation During Home Menu", false, false };
|
||||
|
||||
} misc{ this };
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Emu/Io/pad_config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/RSX/Overlays/overlay_home_menu.h"
|
||||
#include "Emu/RSX/Overlays/overlay_message.h"
|
||||
#include "Utilities/Thread.h"
|
||||
#include "util/atomic.hpp"
|
||||
@ -315,7 +316,7 @@ void pad_thread::operator()()
|
||||
if (!pad::g_enabled || !is_input_allowed())
|
||||
{
|
||||
m_resume_emulation_flag = false;
|
||||
m_mask_start_press_to_unpause = 0;
|
||||
m_mask_start_press_to_resume = 0;
|
||||
thread_ctrl::wait_for(30'000);
|
||||
continue;
|
||||
}
|
||||
@ -399,6 +400,41 @@ void pad_thread::operator()()
|
||||
}
|
||||
}
|
||||
|
||||
// Handle home menu if requested
|
||||
if (!m_home_menu_open && Emu.IsRunning())
|
||||
{
|
||||
for (usz i = 0; i < m_pads.size(); i++)
|
||||
{
|
||||
const auto& pad = m_pads[i];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
continue;
|
||||
|
||||
for (const auto& button : pad->m_buttons)
|
||||
{
|
||||
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2 && button.m_outKeyCode == CELL_PAD_CTRL_PS && button.m_pressed)
|
||||
{
|
||||
open_home_menu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle paused emulation (if triggered by home menu).
|
||||
if (m_home_menu_open && g_cfg.misc.pause_during_home_menu)
|
||||
{
|
||||
// Reset resume control if the home menu is open
|
||||
m_resume_emulation_flag = false;
|
||||
m_mask_start_press_to_resume = 0;
|
||||
m_track_start_press_begin_timestamp = 0;
|
||||
|
||||
// Update UI
|
||||
rsx::set_native_ui_flip();
|
||||
thread_ctrl::wait_for(33'000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_resume_emulation_flag)
|
||||
{
|
||||
m_resume_emulation_flag = false;
|
||||
@ -435,15 +471,15 @@ void pad_thread::operator()()
|
||||
}
|
||||
}
|
||||
|
||||
m_mask_start_press_to_unpause &= pressed_mask;
|
||||
m_mask_start_press_to_resume &= pressed_mask;
|
||||
|
||||
if (!pressed_mask || timestamp - m_track_start_press_begin_timestamp >= 700'000)
|
||||
{
|
||||
m_track_start_press_begin_timestamp = timestamp;
|
||||
|
||||
if (std::exchange(m_mask_start_press_to_unpause, u32{umax}))
|
||||
if (std::exchange(m_mask_start_press_to_resume, u32{umax}))
|
||||
{
|
||||
m_mask_start_press_to_unpause = 0;
|
||||
m_mask_start_press_to_resume = 0;
|
||||
m_track_start_press_begin_timestamp = 0;
|
||||
|
||||
sys_log.success("Resuming emulation using the START button in a few seconds...");
|
||||
@ -471,8 +507,8 @@ void pad_thread::operator()()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset unpause control if caught a state of unpaused emulation
|
||||
m_mask_start_press_to_unpause = 0;
|
||||
// Reset resume control if caught a state of unpaused emulation
|
||||
m_mask_start_press_to_resume = 0;
|
||||
m_track_start_press_begin_timestamp = 0;
|
||||
}
|
||||
|
||||
@ -577,3 +613,34 @@ void pad_thread::InitPadConfig(cfg_pad& cfg, pad_handler type, std::shared_ptr<P
|
||||
ensure(!!handler);
|
||||
handler->init_config(&cfg);
|
||||
}
|
||||
|
||||
extern bool send_open_home_menu_cmds();
|
||||
extern void send_close_home_menu_cmds();
|
||||
|
||||
void pad_thread::open_home_menu()
|
||||
{
|
||||
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
|
||||
{
|
||||
if (m_home_menu_open.exchange(true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!send_open_home_menu_cmds())
|
||||
{
|
||||
m_home_menu_open = false;
|
||||
return;
|
||||
}
|
||||
|
||||
input_log.warning("opening home menu...");
|
||||
|
||||
const error_code result = manager->create<rsx::overlays::home_menu_dialog>()->show([this](s32 status)
|
||||
{
|
||||
input_log.notice("closing home menu with status %d", status);
|
||||
|
||||
m_home_menu_open = false;
|
||||
|
||||
send_close_home_menu_cmds();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ public:
|
||||
s32 AddLddPad();
|
||||
void UnregisterLddPad(u32 handle);
|
||||
|
||||
void open_home_menu();
|
||||
|
||||
static std::shared_ptr<PadHandlerBase> GetHandler(pad_handler type);
|
||||
static void InitPadConfig(cfg_pad& cfg, pad_handler type, std::shared_ptr<PadHandlerBase>& handler);
|
||||
|
||||
@ -54,9 +56,10 @@ protected:
|
||||
u32 num_ldd_pad = 0;
|
||||
|
||||
private:
|
||||
u32 m_mask_start_press_to_unpause = 0;
|
||||
u32 m_mask_start_press_to_resume = 0;
|
||||
u64 m_track_start_press_begin_timestamp = 0;
|
||||
bool m_resume_emulation_flag = false;
|
||||
atomic_t<bool> m_home_menu_open = false;
|
||||
};
|
||||
|
||||
namespace pad
|
||||
|
@ -86,6 +86,7 @@
|
||||
<ClCompile Include="Emu\RSX\Common\texture_cache.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_controls.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_cursor.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_home_menu.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_media_list_dialog.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_osk_panel.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_user_list_dialog.cpp" />
|
||||
@ -535,6 +536,7 @@
|
||||
<ClInclude Include="Emu\RSX\Core\RSXVertexTypes.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_cursor.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_edit_text.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_home_menu.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_list_view.hpp" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_media_list_dialog.h" />
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_progress_bar.hpp" />
|
||||
|
@ -1111,6 +1111,9 @@
|
||||
<ClCompile Include="Emu\Cell\Modules\HLE_PATCHES.cpp">
|
||||
<Filter>Emu\Cell\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Overlays\overlay_home_menu.cpp">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -2236,6 +2239,9 @@
|
||||
<ClInclude Include="Emu\RSX\Common\expected.hpp">
|
||||
<Filter>Emu\GPU\RSX\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\Overlays\overlay_home_menu.h">
|
||||
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Emu\RSX\Program\GLSLSnippets\GPUDeswizzle.glsl">
|
||||
|
@ -165,6 +165,7 @@ enum class emu_settings_type
|
||||
UseNativeInterface,
|
||||
ShowShaderCompilationHint,
|
||||
WindowTitleFormat,
|
||||
PauseDuringHomeMenu,
|
||||
|
||||
// Network
|
||||
InternetStatus,
|
||||
@ -344,6 +345,7 @@ inline static const QMap<emu_settings_type, cfg_location> settings_location =
|
||||
{ emu_settings_type::ShowShaderCompilationHint, { "Miscellaneous", "Show shader compilation hint"}},
|
||||
{ emu_settings_type::SilenceAllLogs, { "Miscellaneous", "Silence All Logs" }},
|
||||
{ emu_settings_type::WindowTitleFormat, { "Miscellaneous", "Window Title Format" }},
|
||||
{ emu_settings_type::PauseDuringHomeMenu, { "Miscellaneous", "Pause Emulation During Home Menu" }},
|
||||
|
||||
// Networking
|
||||
{ emu_settings_type::InternetStatus, { "Net", "Internet enabled"}},
|
||||
|
@ -46,6 +46,8 @@ LOG_CHANNEL(screenshot_log, "SCREENSHOT");
|
||||
LOG_CHANNEL(mark_log, "MARK");
|
||||
LOG_CHANNEL(gui_log, "GUI");
|
||||
|
||||
extern atomic_t<bool> g_user_asked_for_recording;
|
||||
extern atomic_t<bool> g_user_asked_for_screenshot;
|
||||
extern atomic_t<bool> g_user_asked_for_frame_capture;
|
||||
extern atomic_t<bool> g_disable_frame_limit;
|
||||
extern atomic_t<recording_mode> g_recording_mode;
|
||||
@ -142,7 +144,7 @@ gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon,
|
||||
|
||||
gs_frame::~gs_frame()
|
||||
{
|
||||
screenshot_toggle = false;
|
||||
g_user_asked_for_screenshot = false;
|
||||
}
|
||||
|
||||
void gs_frame::paintEvent(QPaintEvent *event)
|
||||
@ -310,7 +312,7 @@ void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKey
|
||||
}
|
||||
case gui::shortcuts::shortcut::gw_screenshot:
|
||||
{
|
||||
screenshot_toggle = true;
|
||||
g_user_asked_for_screenshot = true;
|
||||
break;
|
||||
}
|
||||
case gui::shortcuts::shortcut::gw_toggle_recording:
|
||||
@ -724,6 +726,14 @@ void gs_frame::flip(draw_context_t, bool /*skip_frame*/)
|
||||
m_frames = 0;
|
||||
fps_t.Start();
|
||||
}
|
||||
|
||||
if (g_user_asked_for_recording.exchange(false))
|
||||
{
|
||||
Emu.CallFromMainThread([this]()
|
||||
{
|
||||
toggle_recording();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool gs_frame::can_consume_frame() const
|
||||
|
@ -168,6 +168,11 @@ private:
|
||||
case localized_string_id::RPCN_ERROR_INVALID_PROTOCOL_VERSION: return tr("RPCN Misc Error: Protocol Version Error (outdated RPCS3?)");
|
||||
case localized_string_id::RPCN_ERROR_UNKNOWN: return tr("RPCN: Unknown Error");
|
||||
case localized_string_id::RPCN_SUCCESS_LOGGED_ON: return tr("Successfully logged on RPCN!");
|
||||
case localized_string_id::HOME_MENU_TITLE: return tr("Home Menu");
|
||||
case localized_string_id::HOME_MENU_EXIT_GAME: return tr("Exit Game");
|
||||
case localized_string_id::HOME_MENU_RESUME: return tr("Resume Game");
|
||||
case localized_string_id::HOME_MENU_SCREENSHOT: return tr("Take Screenshot");
|
||||
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...!");
|
||||
case localized_string_id::EMULATION_FROZEN: return tr("The PS3 application has likely crashed, you can close it.");
|
||||
|
@ -1560,9 +1560,6 @@ void main_window::HandlePupInstallation(const QString& file_path, const QString&
|
||||
}
|
||||
}
|
||||
|
||||
// This is ugly, but PS3 headers shall not be included there.
|
||||
extern s32 sysutil_send_system_cmd(u64 status, u64 param);
|
||||
|
||||
void main_window::DecryptSPRXLibraries()
|
||||
{
|
||||
QString path_last_sprx = m_gui_settings->GetValue(gui::fd_decrypt_sprx).toString();
|
||||
|
@ -1626,6 +1626,9 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
m_emu_settings->EnhanceCheckBox(ui->showShaderCompilationHint, emu_settings_type::ShowShaderCompilationHint);
|
||||
SubscribeTooltip(ui->showShaderCompilationHint, tooltips.settings.show_shader_compilation_hint);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->pauseDuringHomeMenu, emu_settings_type::PauseDuringHomeMenu);
|
||||
SubscribeTooltip(ui->pauseDuringHomeMenu, tooltips.settings.pause_during_home_menu);
|
||||
|
||||
m_emu_settings->EnhanceCheckBox(ui->perfOverlayCenterX, emu_settings_type::PerfOverlayCenterX);
|
||||
SubscribeTooltip(ui->perfOverlayCenterX, tooltips.settings.perf_overlay_center_x);
|
||||
connect(ui->perfOverlayCenterX, &QCheckBox::toggled, [this](bool checked)
|
||||
|
@ -2862,6 +2862,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="pauseDuringHomeMenu">
|
||||
<property name="text">
|
||||
<string>Pause emulation during home menu</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="emulatorTabSpacerLeft">
|
||||
<property name="orientation">
|
||||
|
@ -134,6 +134,7 @@ public:
|
||||
const QString hide_mouse_on_idle = tr("Hides the mouse cursor if no mouse movement is detected for the configured time.");
|
||||
const QString show_shader_compilation_hint = tr("Shows 'Compiling shaders' hint using the native overlay.");
|
||||
const QString use_native_interface = tr("Enables use of native HUD within the game window that can interact with game controllers.\nWhen disabled, regular Qt dialogs are used instead.\nCurrently, the on-screen keyboard only supports the English key layout.");
|
||||
const QString pause_during_home_menu = tr("When enabled, opening the home menu will also pause emulation.\nWhile most games pause themselves while the home menu is shown, some do not.\nIn that case it can be helpful to pause the emulation whenever the home menu is open.");
|
||||
|
||||
const QString perf_overlay_enabled = tr("Enables or disables the performance overlay.");
|
||||
const QString perf_overlay_framerate_graph_enabled = tr("Enables or disables the framerate graph.");
|
||||
|
Loading…
Reference in New Issue
Block a user