Skip to content

Commit 03a39f5

Browse files
authored
Merge branch 'master' into twistedmetal
2 parents b83d9c7 + d9799c7 commit 03a39f5

34 files changed

Lines changed: 491 additions & 205 deletions

rpcs3/Crypto/unpkg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,11 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
952952
default:
953953
{
954954
// TODO: check for valid utf8 characters
955-
const std::string true_path = std::filesystem::weakly_canonical(path).string();
955+
const std::string true_path = std::filesystem::path(path).lexically_normal().string();
956956
if (true_path.empty())
957957
{
958958
num_failures++;
959-
pkg_log.error("Failed to get weakly_canonical path for '%s'", path);
959+
pkg_log.error("Failed to normalize package path for '%s'", path);
960960
break;
961961
}
962962

rpcs3/Emu/Cell/lv2/sys_overlay.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ std::function<void(void*)> lv2_overlay::load(utils::serial& ar)
9595
{
9696
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
9797
file = make_file_view(std::move(file), offset, umax);
98-
ovlm = ppu_load_overlay(ppu_exec_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, false, path, 0, &ar).first;
98+
ovlm = ppu_load_overlay(ppu_exec_object{ decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic)) }, false, path, offset, &ar).first;
9999

100100
if (!ovlm)
101101
{

rpcs3/Emu/Cell/lv2/sys_prx.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ std::function<void(void*)> lv2_prx::load(utils::serial& ar)
347347
{
348348
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
349349
file = make_file_view(std::move(file), offset, umax);
350-
prx = ppu_load_prx(ppu_prx_object{decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic))}, false, path, 0, &ar);
350+
prx = ppu_load_prx(ppu_prx_object{decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic))}, false, path, offset, &ar);
351351
prx->m_loaded_flags = std::move(loaded_flags);
352352
prx->m_external_loaded_flags = std::move(external_flags);
353353

@@ -390,7 +390,9 @@ void lv2_prx::save(utils::serial& ar)
390390
{
391391
USING_SERIALIZATION_VERSION(lv2_prx_overlay);
392392

393-
ar(vfs::retrieve(path), offset, state);
393+
const std::string vpath = vfs::retrieve(path);
394+
395+
ar(vpath, offset, state);
394396

395397
// Save segments count
396398
ar.serialize_vle(segs.size());
@@ -401,10 +403,18 @@ void lv2_prx::save(utils::serial& ar)
401403
ar(m_external_loaded_flags);
402404
}
403405

406+
std::string segments;
407+
404408
for (const ppu_segment& seg : segs)
405409
{
406-
if (seg.type == 0x1u && seg.size) ar(seg.addr);
410+
if (seg.type == 0x1u && seg.size)
411+
{
412+
fmt::append(segments, " 0x%x", seg.addr);
413+
ar(seg.addr);
414+
}
407415
}
416+
417+
(vpath.empty() ? sys_prx.error : sys_prx.success)("lv2_prx::save(): vpath='%s', offset=0x%x, state=%x, segments:%s", vpath, offset, +state, segments);
408418
}
409419

410420
error_code sys_prx_get_ppu_guid(ppu_thread& ppu)

rpcs3/Emu/RSX/Common/texture_cache.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ namespace rsx
17841784
};
17851785

17861786
surface_scaling_config_t scaling_config{};
1787-
if (g_cfg.video.allow_blit_engine_upscaling)
1787+
if (!g_cfg.video.disable_blit_engine_upscaling)
17881788
{
17891789
scaling_config =
17901790
{
@@ -3740,6 +3740,13 @@ namespace rsx
37403740
}
37413741
}
37423742

3743+
// MM flush before commit below. For performance reasons, only flush when writing to CELL memory.
3744+
if (rsx::classify_location(dst.rsx_address) == CELL_GCM_LOCATION_MAIN)
3745+
{
3746+
const auto mm_flush_range = utils::address_range64::start_length(reinterpret_cast<u64>(dst.pixels), dst_payload_length);
3747+
rsx::mm_flush({ mm_flush_range });
3748+
}
3749+
37433750
// Commit any pending writes before we do the transfer. Writes will be done on super_ptr so locking beforehand is ok.
37443751
m_rtts.prepare_transfer_target(cmd, dst_subres.surface, rsx::surface_access::transfer_write, std::forward<Args>(extras)...);
37453752
}

rpcs3/Emu/RSX/Common/texture_cache_helpers.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,14 @@ namespace rsx
232232

233233
if (src_is_render_target)
234234
{
235-
// Attempt to optimize...
236-
if (dst_dimensions.width == 1280 || dst_dimensions.width == 2560) [[likely]]
235+
// Attempt to optimize for performance...
236+
if (get_location(dst_range.start) == CELL_GCM_LOCATION_MAIN)
237+
{
238+
// Don't guess when working with main memory
239+
const auto min_fitted_height = utils::aligned_div(dst_range.length(), dst_pitch);
240+
dst_dimensions.height = std::min(dst_dimensions.height, min_fitted_height);
241+
}
242+
else if (dst_dimensions.width == 1280 || dst_dimensions.width == 2560)
237243
{
238244
// Optimizations table based on common width/height pairings. If we guess wrong, the upload resolver will fix it anyway
239245
// TODO: Add more entries based on empirical data

rpcs3/Emu/RSX/Host/MM.cpp

Lines changed: 121 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,113 @@ namespace rsx
1414
rsx::simple_array<MM_block> g_deferred_mprotect_queue;
1515
shared_mutex g_mprotect_queue_lock;
1616

17-
void mm_flush_mprotect_queue_internal()
17+
void mm_sanitize_queue_internal()
1818
{
19-
for (const auto& block : g_deferred_mprotect_queue)
19+
u32 w = 0, r = 0;
20+
for (; r < g_deferred_mprotect_queue.size(); ++r)
2021
{
22+
auto& block = g_deferred_mprotect_queue[r];
23+
if (!block.range.valid())
24+
{
25+
continue;
26+
}
27+
g_deferred_mprotect_queue[w++] = block;
28+
}
29+
g_deferred_mprotect_queue.resize(w);
30+
}
31+
32+
void mm_flush_mprotect_queue_internal(u32 count)
33+
{
34+
AUDIT(count <= g_deferred_mprotect_queue.size());
35+
36+
for (u32 i = 0; i < count; ++i)
37+
{
38+
auto& block = g_deferred_mprotect_queue[i];
39+
ensure(block.range.valid());
40+
2141
utils::memory_protect(reinterpret_cast<void*>(block.range.start), block.range.length(), block.prot);
42+
block.range.invalidate();
43+
}
44+
45+
const u32 remaining = g_deferred_mprotect_queue.size() - count;
46+
if (!remaining)
47+
{
48+
g_deferred_mprotect_queue.clear();
49+
return;
50+
}
51+
52+
// Pop processed entries from the queue
53+
mm_sanitize_queue_internal();
54+
}
55+
56+
// Reverse scan to find the latest overlapping MM conflict. The result is a count of prefix blocks.
57+
template <typename F>
58+
u32 mm_find_conflict_internal(F&& predicate)
59+
{
60+
for (u32 i = g_deferred_mprotect_queue.size(); i > 0; --i)
61+
{
62+
if (std::invoke(predicate, g_deferred_mprotect_queue[i - 1]))
63+
{
64+
return i;
65+
}
2266
}
2367

24-
g_deferred_mprotect_queue.clear();
68+
return 0;
2569
}
2670

2771
void mm_defer_mprotect_internal(u64 start, u64 length, utils::protection prot)
2872
{
29-
// We could stack and merge requests here, but that is more trouble than it is truly worth.
30-
// A fresh call to memory_protect only takes a few nanoseconds of setup overhead, it is not worth the risk of hanging because of conflicts.
31-
g_deferred_mprotect_queue.push_back({ utils::address_range64::start_length(start, length), prot });
73+
const auto range = utils::address_range64::start_length(start, length);
74+
bool has_invalid = false;
75+
bool is_merged = false;
76+
77+
// Attempt a merge first. The queue length is short but the time taken to run mprotect is very high in comparison.
78+
for (auto it = g_deferred_mprotect_queue.rbegin();
79+
it != g_deferred_mprotect_queue.rend();
80+
++it)
81+
{
82+
auto& block = *it;
83+
if (!block.touches(range))
84+
{
85+
continue;
86+
}
87+
88+
if (block.prot != prot)
89+
{
90+
// Optimization. If our new range swallows the old one, replace it.
91+
if (block.range.inside(range))
92+
{
93+
block.range.invalidate();
94+
has_invalid = true;
95+
continue;
96+
}
97+
98+
if (!block.overlaps(range))
99+
{
100+
// Adjacent. Skip.
101+
continue;
102+
}
103+
104+
// Preserve ordering. Do not proceed with merge.
105+
break;
106+
}
107+
108+
block.merge(range);
109+
is_merged = true;
110+
break;
111+
}
112+
113+
if (has_invalid)
114+
{
115+
mm_sanitize_queue_internal();
116+
}
117+
118+
if (is_merged)
119+
{
120+
return;
121+
}
122+
123+
g_deferred_mprotect_queue.push_back({ range, prot });
32124
}
33125

34126
void mm_protect(void* ptr, u64 length, utils::protection prot)
@@ -47,13 +139,24 @@ namespace rsx
47139

48140
if (prot == utils::protection::rw || prot == utils::protection::wx)
49141
{
50-
// Basically an unlock op. Flush if any overlap is detected
51-
for (const auto& block : g_deferred_mprotect_queue)
142+
// Basically an unlock op. Flush the conflicting prefix block if any overlap is detected.
143+
if (u32 count = mm_find_conflict_internal(FN(x.overlaps(range))))
52144
{
53-
if (block.overlaps(range))
145+
// Check for degenerate ranges that we'll be crushing
146+
for (auto pblock = &g_deferred_mprotect_queue[count - 1];
147+
count > 0 && pblock->range.inside(range);
148+
count--, pblock--)
54149
{
55-
mm_flush_mprotect_queue_internal();
56-
break;
150+
pblock->range.invalidate();
151+
}
152+
153+
if (count)
154+
{
155+
mm_flush_mprotect_queue_internal(count);
156+
}
157+
else
158+
{
159+
mm_sanitize_queue_internal();
57160
}
58161
}
59162

@@ -68,7 +171,7 @@ namespace rsx
68171
void mm_flush()
69172
{
70173
std::lock_guard lock(g_mprotect_queue_lock);
71-
mm_flush_mprotect_queue_internal();
174+
mm_flush_mprotect_queue_internal(g_deferred_mprotect_queue.size());
72175
}
73176

74177
void mm_flush(u32 vm_address)
@@ -80,31 +183,24 @@ namespace rsx
80183
}
81184

82185
const auto addr = reinterpret_cast<u64>(vm::base(vm_address));
83-
for (const auto& block : g_deferred_mprotect_queue)
186+
if (const u32 count = mm_find_conflict_internal(FN(x.overlaps(addr))))
84187
{
85-
if (block.overlaps(addr))
86-
{
87-
mm_flush_mprotect_queue_internal();
88-
return;
89-
}
188+
mm_flush_mprotect_queue_internal(count);
90189
}
91190
}
92191

93192
void mm_flush(const rsx::simple_array<utils::address_range64>& ranges)
94193
{
95194
std::lock_guard lock(g_mprotect_queue_lock);
96-
if (g_deferred_mprotect_queue.empty())
195+
if (g_deferred_mprotect_queue.empty() || ranges.empty())
97196
{
98197
return;
99198
}
100199

101-
for (const auto& block : g_deferred_mprotect_queue)
200+
const auto block_overlaps_ranges = [&](const MM_block& block) { return ranges.any(FN(block.overlaps(x))); };
201+
if (const u32 count = mm_find_conflict_internal(block_overlaps_ranges))
102202
{
103-
if (ranges.any(FN(block.overlaps(x))))
104-
{
105-
mm_flush_mprotect_queue_internal();
106-
return;
107-
}
203+
mm_flush_mprotect_queue_internal(count);
108204
}
109205
}
110206

rpcs3/Emu/RSX/Host/MM.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ namespace rsx
1313
utils::address_range64 range;
1414
utils::protection prot;
1515

16+
inline void merge(const utils::address_range64& other)
17+
{
18+
AUDIT(other.valid());
19+
range = utils::address_range64::start_end(
20+
std::min(range.start, other.start),
21+
std::max(range.end, other.end)
22+
);
23+
}
24+
1625
inline bool overlaps(const utils::address_range64& test) const
1726
{
1827
return range.overlaps(test);
@@ -22,6 +31,11 @@ namespace rsx
2231
{
2332
return range.overlaps(addr);
2433
}
34+
35+
inline bool touches(const utils::address_range64& test) const
36+
{
37+
return range.touches(test);
38+
}
2539
};
2640

2741
enum mm_backend_ctrl : u32

rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#pragma once
22

33
#include "Emu/RSX/Overlays/overlays.h"
4-
#include "Emu/Cell/ErrorCodes.h"
54
#include "overlay_big_picture_main_menu.h"
65

76
namespace rsx

rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_details.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "stdafx.h"
22
#include "overlay_big_picture_game_details.h"
3-
#include "Emu/RSX/Overlays/HomeMenu/overlay_home_menu_components.h"
3+
#include "Emu/system_utils.hpp"
44

55
namespace rsx
66
{
@@ -51,9 +51,7 @@ namespace rsx
5151

5252
m_info_text.set_text(fmt::format("%s\n%s\n%s", info.serial, info.category, info.app_ver));
5353

54-
const std::string game_dir = fs::get_parent_dir(info.icon_path);
55-
56-
if (const std::string pic1_path = game_dir + "/PIC1.PNG"; fs::is_file(pic1_path))
54+
if (const std::string pic1_path = rpcs3::utils::get_game_content_path(game_content_type::background_picture, info); !pic1_path.empty())
5755
{
5856
m_pic_data = std::make_unique<image_info>(pic1_path);
5957
// The renderer's texture cache is keyed by this object's address, which can be reused by an
@@ -71,9 +69,9 @@ namespace rsx
7169

7270
m_pic_background.refresh();
7371

74-
if (const std::string icon1_path = game_dir + "/ICON1.PAM"; fs::is_file(icon1_path))
72+
if (!info.movie_path.empty())
7573
{
76-
m_video = std::make_unique<video_view>(icon1_path, "", info.icon_path);
74+
m_video = std::make_unique<video_view>(info.movie_path, info.audio_path, info.icon_path);
7775
m_video->set_pos(m_icon.x, m_icon.y);
7876
m_video->set_size(m_icon.w, m_icon.h);
7977
m_video->set_active(true);

rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ namespace rsx
109109

110110
GameInfo info{};
111111
info.path = path;
112-
info.icon_path = sfo_dir + "/ICON0.PNG";
113112
info.serial = title_id;
114113
info.name = std::string(psf::get_string(psf, "TITLE", title_id));
115114
info.category = std::string(psf::get_string(psf, "CATEGORY"));
116115
info.app_ver = std::string(psf::get_string(psf, "APP_VER"));
116+
info.icon_path = rpcs3::utils::get_game_content_path(game_content_type::content_icon, info, sfo_dir);
117+
info.movie_path = rpcs3::utils::get_game_content_path(game_content_type::content_video, info, sfo_dir);
118+
info.audio_path = rpcs3::utils::get_game_content_path(game_content_type::content_sound, info, sfo_dir);
117119

118120
m_games.push_back({ std::move(info) });
119121
}
@@ -290,9 +292,9 @@ namespace rsx
290292
break;
291293
case pad_button::dpad_down:
292294
case pad_button::ls_down:
293-
if ((m_selected_index + m_columns) < static_cast<s32>(m_tiles.size()))
295+
if (!m_tiles.empty())
294296
{
295-
select_tile(m_selected_index + m_columns);
297+
select_tile(std::min(m_selected_index + m_columns, static_cast<s32>(m_tiles.size()) - 1));
296298
}
297299
break;
298300
case pad_button::cross:

0 commit comments

Comments
 (0)