1
0
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:
Megamouse 2023-01-14 00:07:07 +01:00
parent ac2b2d82d2
commit 44771150b7
27 changed files with 482 additions and 33 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View 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

View 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);
};
}
}

View File

@ -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());

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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 };

View File

@ -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();
});
}
}

View File

@ -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

View File

@ -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" />

View File

@ -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">

View File

@ -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"}},

View File

@ -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

View File

@ -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.");

View File

@ -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();

View File

@ -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)

View File

@ -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">

View File

@ -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.");