Compare commits

...

5 Commits

Author SHA1 Message Date
NicknineTheEagle 05b89eca9d
Merge 7f4ba5afe4 into 66eae05e75 2024-09-19 01:06:25 +02:00
capriots 66eae05e75 cellAtracXdec: fix FFmpeg warning 2024-09-18 07:57:10 +02:00
Elad Ashkenazi 7f4ba5afe4
Merge branch 'master' into nn/auto-indicator 2024-06-28 20:54:54 +03:00
NicknineTheEagle abf454718f cellSaveData: Add autosave indicator 2024-06-22 14:40:48 +03:00
NicknineTheEagle fb06a7d5d0 Overlays: Add top right and bottom right messages 2024-06-22 14:39:53 +03:00
6 changed files with 114 additions and 13 deletions

View File

@ -121,6 +121,7 @@ void AtracXdecDecoder::alloc_avcodec()
// Allows FFmpeg to output directly into guest memory // Allows FFmpeg to output directly into guest memory
ctx->opaque = this; ctx->opaque = this;
ctx->thread_type = FF_THREAD_SLICE; // Silences a warning by FFmpeg about requesting frame threading with a custom get_buffer2(). Default is FF_THREAD_FRAME & FF_THREAD_SLICE
ctx->get_buffer2 = [](AVCodecContext* s, AVFrame* frame, int /*flags*/) -> int ctx->get_buffer2 = [](AVCodecContext* s, AVFrame* frame, int /*flags*/) -> int
{ {
for (s32 i = 0; i < frame->ch_layout.nb_channels; i++) for (s32 i = 0; i < frame->ch_layout.nb_channels; i++)

View File

@ -10,6 +10,7 @@
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/Modules/cellSysutil.h" #include "Emu/Cell/Modules/cellSysutil.h"
#include "Emu/Cell/Modules/cellUserInfo.h" #include "Emu/Cell/Modules/cellUserInfo.h"
#include "Emu/RSX/Overlays/overlay_message.h"
#include "cellSaveData.h" #include "cellSaveData.h"
#include "cellMsgDialog.h" #include "cellMsgDialog.h"
@ -1750,6 +1751,48 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
fileGet->excSize = 0; fileGet->excSize = 0;
// show indicator for automatic save or auto load interactions if the game requests it (statSet->indicator)
const bool show_auto_indicator = operation <= SAVEDATA_OP_LIST_AUTO_LOAD && statSet && statSet->indicator;
if (show_auto_indicator)
{
auto msg_text = localized_string_id::INVALID;
if (operation == SAVEDATA_OP_AUTO_SAVE || operation == SAVEDATA_OP_LIST_AUTO_SAVE)
{
msg_text = localized_string_id::CELL_SAVEDATA_AUTOSAVE;
}
else if (operation == SAVEDATA_OP_AUTO_LOAD || operation == SAVEDATA_OP_LIST_AUTO_LOAD)
{
msg_text = localized_string_id::CELL_SAVEDATA_AUTOLOAD;
}
u32 indicator_pos = (statSet->indicator->dispPosition & 0x0F);
auto msg_location = rsx::overlays::message_pin_location::top;
switch (indicator_pos)
{
case CELL_SAVEDATA_INDICATORPOS_UPPER_LEFT:
msg_location = rsx::overlays::message_pin_location::top;
break;
case CELL_SAVEDATA_INDICATORPOS_LOWER_LEFT:
msg_location = rsx::overlays::message_pin_location::bottom;
break;
case CELL_SAVEDATA_INDICATORPOS_UPPER_RIGHT:
msg_location = rsx::overlays::message_pin_location::top_right;
break;
case CELL_SAVEDATA_INDICATORPOS_LOWER_RIGHT:
msg_location = rsx::overlays::message_pin_location::bottom_right;
break;
}
// TODO: Blinking variants
// RPCS3 saves basically instantaneously so there's not much point in showing auto indicator
// WHILE saving is in progress. Instead we show the indicator for 3 seconds to let the user
// know when the game autosaves.
rsx::overlays::queue_message(msg_text, 3'000'000, {}, msg_location);
}
error_code savedata_result = CELL_OK; error_code savedata_result = CELL_OK;
u64 delay_save_until = 0; u64 delay_save_until = 0;
@ -2098,6 +2141,11 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
fs::remove_all(old_path); fs::remove_all(old_path);
} }
if (show_auto_indicator)
{
// auto indicator should be hidden here if save/load throttling is added
}
if (savedata_result + 0u == CELL_SAVEDATA_ERROR_CBRESULT) if (savedata_result + 0u == CELL_SAVEDATA_ERROR_CBRESULT)
{ {
return display_callback_result_error_message(ppu, *result, errDialog); return display_callback_result_error_message(ppu, *result, errDialog);

View File

@ -117,12 +117,12 @@ namespace rsx
return compiled_resources; return compiled_resources;
} }
void message_item::update(usz index, u64 timestamp_us, s16 y_offset) void message_item::update(usz index, u64 timestamp_us, s16 x_offset, s16 y_offset)
{ {
if (m_cur_pos != index) if (m_cur_pos != index)
{ {
m_cur_pos = index; m_cur_pos = index;
set_pos(10, y_offset); set_pos(x_offset, y_offset);
} }
if (!m_processed) if (!m_processed)
@ -198,18 +198,29 @@ namespace rsx
// Render reversed list. Oldest entries are furthest from the border // Render reversed list. Oldest entries are furthest from the border
constexpr u16 spacing = 4; constexpr u16 spacing = 4;
s16 y_offset = 8; s16 y_offset = 8;
s16 x_offset = 10;
usz index = 0; usz index = 0;
for (auto it = vis_set.rbegin(); it != vis_set.rend(); ++it, ++index) for (auto it = vis_set.rbegin(); it != vis_set.rend(); ++it, ++index)
{ {
if (origin == message_pin_location::top) [[ likely ]] if (origin == message_pin_location::top) [[ likely ]]
{ {
it->update(index, cur_time, y_offset); it->update(index, cur_time, x_offset, y_offset);
y_offset += (spacing + it->h); y_offset += (spacing + it->h);
} }
else else if (origin == message_pin_location::bottom)
{ {
y_offset += (spacing + it->h); y_offset += (spacing + it->h);
it->update(index, cur_time, virtual_height - y_offset); it->update(index, cur_time, x_offset, virtual_height - y_offset);
}
else if (origin == message_pin_location::top_right)
{
it->update(index, cur_time, virtual_width - x_offset - it->w, y_offset);
y_offset += (spacing + it->h);
}
else if (origin == message_pin_location::bottom_right)
{
y_offset += (spacing + it->h);
it->update(index, cur_time, virtual_width - x_offset - it->w, virtual_height - y_offset);
} }
} }
} }
@ -225,8 +236,11 @@ namespace rsx
update_queue(m_visible_items_top, m_ready_queue_top, message_pin_location::top); update_queue(m_visible_items_top, m_ready_queue_top, message_pin_location::top);
update_queue(m_visible_items_bottom, m_ready_queue_bottom, message_pin_location::bottom); update_queue(m_visible_items_bottom, m_ready_queue_bottom, message_pin_location::bottom);
update_queue(m_visible_items_top_right, m_ready_queue_top_right, message_pin_location::top_right);
update_queue(m_visible_items_bottom_right, m_ready_queue_bottom_right, message_pin_location::bottom_right);
visible = !m_visible_items_top.empty() || !m_visible_items_bottom.empty(); visible = !m_visible_items_top.empty() || !m_visible_items_bottom.empty() ||
!m_visible_items_top_right.empty() || !m_visible_items_bottom_right.empty();
} }
compiled_resource message::get_compiled() compiled_resource message::get_compiled()
@ -250,6 +264,16 @@ namespace rsx
cr.add(item.get_compiled()); cr.add(item.get_compiled());
} }
for (auto& item : m_visible_items_top_right)
{
cr.add(item.get_compiled());
}
for (auto& item : m_visible_items_bottom_right)
{
cr.add(item.get_compiled());
}
return cr; return cr;
} }
@ -287,6 +311,10 @@ namespace rsx
return check_list(m_ready_queue_top) || check_list(m_visible_items_top); return check_list(m_ready_queue_top) || check_list(m_visible_items_top);
case message_pin_location::bottom: case message_pin_location::bottom:
return check_list(m_ready_queue_bottom) || check_list(m_visible_items_bottom); return check_list(m_ready_queue_bottom) || check_list(m_visible_items_bottom);
case message_pin_location::top_right:
return check_list(m_ready_queue_top_right) || check_list(m_visible_items_top_right);
case message_pin_location::bottom_right:
return check_list(m_ready_queue_bottom_right) || check_list(m_visible_items_bottom_right);
} }
return false; return false;

View File

@ -12,7 +12,9 @@ namespace rsx
enum class message_pin_location enum class message_pin_location
{ {
top, top,
bottom bottom,
top_right,
bottom_right
}; };
class message_item : public rounded_rect class message_item : public rounded_rect
@ -20,7 +22,7 @@ namespace rsx
public: public:
template <typename T> template <typename T>
message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs, std::shared_ptr<overlay_element> icon = {}); message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs, std::shared_ptr<overlay_element> icon = {});
void update(usz index, u64 timestamp_us, s16 y_offset); void update(usz index, u64 timestamp_us, s16 x_offset, s16 y_offset);
void set_pos(s16 _x, s16 _y) override; void set_pos(s16 _x, s16 _y) override;
void reset_expiration(); void reset_expiration();
@ -61,9 +63,23 @@ namespace rsx
{ {
std::lock_guard lock(m_mutex_queue); std::lock_guard lock(m_mutex_queue);
auto& queue = location == message_pin_location::top auto* queue = &m_ready_queue_top;
? m_ready_queue_top
: m_ready_queue_bottom; switch (location)
{
case message_pin_location::top:
queue = &m_ready_queue_top;
break;
case message_pin_location::bottom:
queue = &m_ready_queue_bottom;
break;
case message_pin_location::top_right:
queue = &m_ready_queue_top_right;
break;
case message_pin_location::bottom_right:
queue = &m_ready_queue_bottom_right;
break;
}
if constexpr (std::is_same_v<T, std::initializer_list<localized_string_id>>) if constexpr (std::is_same_v<T, std::initializer_list<localized_string_id>>)
{ {
@ -71,13 +87,13 @@ namespace rsx
{ {
if (!message_exists(location, id, allow_refresh)) if (!message_exists(location, id, allow_refresh))
{ {
queue.emplace_back(id, expiration, refs, icon); queue->emplace_back(id, expiration, refs, icon);
} }
} }
} }
else if (!message_exists(location, msg_id, allow_refresh)) else if (!message_exists(location, msg_id, allow_refresh))
{ {
queue.emplace_back(msg_id, expiration, std::move(refs), icon); queue->emplace_back(msg_id, expiration, std::move(refs), icon);
} }
visible = true; visible = true;
@ -91,10 +107,14 @@ namespace rsx
// Top and bottom enqueued sets // Top and bottom enqueued sets
std::deque<message_item> m_ready_queue_top; std::deque<message_item> m_ready_queue_top;
std::deque<message_item> m_ready_queue_bottom; std::deque<message_item> m_ready_queue_bottom;
std::deque<message_item> m_ready_queue_top_right;
std::deque<message_item> m_ready_queue_bottom_right;
// Top and bottom visible sets // Top and bottom visible sets
std::deque<message_item> m_visible_items_top; std::deque<message_item> m_visible_items_top;
std::deque<message_item> m_visible_items_bottom; std::deque<message_item> m_visible_items_bottom;
std::deque<message_item> m_visible_items_top_right;
std::deque<message_item> m_visible_items_bottom_right;
void update_queue(std::deque<message_item>& vis_set, std::deque<message_item>& ready_set, message_pin_location origin); void update_queue(std::deque<message_item>& vis_set, std::deque<message_item>& ready_set, message_pin_location origin);

View File

@ -138,6 +138,8 @@ enum class localized_string_id
CELL_SAVEDATA_SAVE, CELL_SAVEDATA_SAVE,
CELL_SAVEDATA_LOAD, CELL_SAVEDATA_LOAD,
CELL_SAVEDATA_OVERWRITE, CELL_SAVEDATA_OVERWRITE,
CELL_SAVEDATA_AUTOSAVE,
CELL_SAVEDATA_AUTOLOAD,
CELL_CROSS_CONTROLLER_MSG, CELL_CROSS_CONTROLLER_MSG,
CELL_CROSS_CONTROLLER_FW_MSG, CELL_CROSS_CONTROLLER_FW_MSG,

View File

@ -165,6 +165,8 @@ private:
case localized_string_id::CELL_SAVEDATA_DELETE: return tr("Delete this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_DELETE: return tr("Delete this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_LOAD: return tr("Load this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_LOAD: return tr("Load this data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_OVERWRITE: return tr("Do you want to overwrite the saved data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...); case localized_string_id::CELL_SAVEDATA_OVERWRITE: return tr("Do you want to overwrite the saved data?\n\n%0", "Savedata entry info").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_SAVEDATA_AUTOSAVE: return tr("Saving...");
case localized_string_id::CELL_SAVEDATA_AUTOLOAD: return tr("Loading...");
case localized_string_id::CELL_CROSS_CONTROLLER_MSG: return tr("Start [%0] on the PS Vita system.\nIf you have not installed [%0], go to [Remote Play] on the PS Vita system and start [Cross-Controller] from the LiveArea™ screen.", "Cross-Controller message").arg(std::forward<Args>(args)...); case localized_string_id::CELL_CROSS_CONTROLLER_MSG: return tr("Start [%0] on the PS Vita system.\nIf you have not installed [%0], go to [Remote Play] on the PS Vita system and start [Cross-Controller] from the LiveArea™ screen.", "Cross-Controller message").arg(std::forward<Args>(args)...);
case localized_string_id::CELL_CROSS_CONTROLLER_FW_MSG: return tr("If your system software version on the PS Vita system is earlier than 1.80, you must update the system software to the latest version.", "Cross-Controller firmware message"); case localized_string_id::CELL_CROSS_CONTROLLER_FW_MSG: return tr("If your system software version on the PS Vita system is earlier than 1.80, you must update the system software to the latest version.", "Cross-Controller firmware message");
case localized_string_id::CELL_NP_RECVMESSAGE_DIALOG_TITLE: return tr("Select Message", "RECVMESSAGE_DIALOG"); case localized_string_id::CELL_NP_RECVMESSAGE_DIALOG_TITLE: return tr("Select Message", "RECVMESSAGE_DIALOG");