Skip to content

Commit d66ce56

Browse files
committed
PPU LLVM: Selective compilation for language based executables
1 parent bb809c8 commit d66ce56

File tree

1 file changed

+174
-8
lines changed

1 file changed

+174
-8
lines changed

rpcs3/Emu/Cell/PPUThread.cpp

+174-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "PPUDisAsm.h"
2222
#include "SPURecompiler.h"
2323
#include "timers.hpp"
24+
#include "Emu/Cell/Modules/cellSysutil.h"
2425
#include "lv2/sys_sync.h"
2526
#include "lv2/sys_prx.h"
2627
#include "lv2/sys_overlay.h"
@@ -3675,13 +3676,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
36753676
struct file_info
36763677
{
36773678
std::string path;
3679+
std::string rec_name;
36783680
u64 offset;
36793681
u64 file_size;
36803682

36813683
file_info() noexcept = default;
36823684

3683-
file_info(std::string _path, u64 offs, u64 size) noexcept
3685+
file_info(std::string _path, std::string _rec, u64 offs, u64 size) noexcept
36843686
: path(std::move(_path))
3687+
, rec_name(std::move(_rec))
36853688
, offset(offs)
36863689
, file_size(size)
36873690
{
@@ -3702,6 +3705,8 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
37023705

37033706
ppu_log.notice("Scanning directory: %s", dir_queue[i]);
37043707

3708+
const usz old_size = file_queue.size();
3709+
37053710
for (auto&& entry : fs::dir(dir_queue[i]))
37063711
{
37073712
if (Emu.IsStopped())
@@ -3773,15 +3778,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
37733778
}
37743779

37753780
// Get full path
3776-
file_queue.emplace_back(dir_queue[i] + entry.name, 0, entry.size);
3781+
file_queue.emplace_back(dir_queue[i] + entry.name, std::string{}, 0, entry.size);
37773782
continue;
37783783
}
37793784

37803785
// Check ELF filename
37813786
if ((upper.ends_with(".ELF") || upper.ends_with(".SELF")) && Emu.GetBoot() != dir_queue[i] + entry.name)
37823787
{
37833788
// Get full path
3784-
file_queue.emplace_back(dir_queue[i] + entry.name, 0, entry.size);
3789+
file_queue.emplace_back(dir_queue[i] + entry.name, std::string{}, 0, entry.size);
37853790
continue;
37863791
}
37873792

@@ -3824,14 +3829,14 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
38243829
if (upper.find(".SPRX") != umax || upper.find(".PRX") != umax)
38253830
{
38263831
// .sprx inside .mself found
3827-
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off, rec.size);
3832+
file_queue.emplace_back(dir_queue[i] + entry.name, std::move(name), rec.off, rec.size);
38283833
continue;
38293834
}
38303835

38313836
if (upper.find(".SELF") != umax || upper.find(".ELF") != umax)
38323837
{
38333838
// .self inside .mself found
3834-
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off, rec.size);
3839+
file_queue.emplace_back(dir_queue[i] + entry.name, std::move(name), rec.off, rec.size);
38353840
continue;
38363841
}
38373842
}
@@ -3845,6 +3850,151 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
38453850
}
38463851
}
38473852
}
3853+
3854+
if (file_queue.size() > old_size + 1)
3855+
{
3856+
// Metal Gear Solid 4 has multiple executables for different languages, and they are massive each!
3857+
// The difference between them is two letters, abbrevation of the language
3858+
// sp.self, us.self, fr.self, gr.self, it.self and jp.self
3859+
3860+
std::string prev_fname;
3861+
usz diff_pos = umax;
3862+
bool has_used_file = false;
3863+
3864+
static const std::unordered_map<std::string_view, s32> s_ch_to_lang =
3865+
{
3866+
{"sp"sv, CELL_SYSUTIL_LANG_SPANISH},
3867+
{"us"sv, CELL_SYSUTIL_LANG_ENGLISH_US},
3868+
{"fr"sv, CELL_SYSUTIL_LANG_FRENCH},
3869+
{"gr"sv, CELL_SYSUTIL_LANG_GERMAN},
3870+
{"it"sv, CELL_SYSUTIL_LANG_ITALIAN},
3871+
{"jp"sv, CELL_SYSUTIL_LANG_JAPANESE},
3872+
};
3873+
3874+
std::string_view chosen_lang;
3875+
3876+
for (auto& [name, key] : s_ch_to_lang)
3877+
{
3878+
if (key == g_cfg.sys.language)
3879+
{
3880+
chosen_lang = name;
3881+
break;
3882+
}
3883+
}
3884+
3885+
if (g_cfg.sys.language == CELL_SYSUTIL_LANG_ENGLISH_GB)
3886+
{
3887+
// Fallback
3888+
chosen_lang = "us"sv;
3889+
}
3890+
3891+
if (chosen_lang.empty())
3892+
{
3893+
// Disable optimization if other langues are selected
3894+
continue;
3895+
}
3896+
3897+
for (usz i = old_size; i < file_queue.size(); i++)
3898+
{
3899+
const std::string_view path = file_queue[i].path;
3900+
std::string fname = fmt::to_lower(path.substr(path.find_last_of(fs::delim) + 1));
3901+
3902+
if (fname.size() >= 7 && fname.ends_with(".self"))
3903+
{
3904+
if (prev_fname.empty())
3905+
{
3906+
prev_fname = std::move(fname);
3907+
}
3908+
else if (!prev_fname.empty() && prev_fname.size() == fname.size())
3909+
{
3910+
usz j = 0;
3911+
3912+
for (; j < fname.size() - 7; j++)
3913+
{
3914+
if (prev_fname[j] != fname[j])
3915+
{
3916+
break;
3917+
}
3918+
}
3919+
3920+
if (diff_pos != umax && j != diff_pos)
3921+
{
3922+
continue;
3923+
}
3924+
3925+
const std::string_view plang = std::string_view(prev_fname).substr(j, 2);
3926+
const std::string_view flang = std::string_view(fname).substr(j, 2);
3927+
3928+
if (plang != flang && s_ch_to_lang.contains(plang) && s_ch_to_lang.contains(flang))
3929+
{
3930+
if (diff_pos == umax)
3931+
{
3932+
diff_pos = j;
3933+
}
3934+
3935+
if (flang == chosen_lang)
3936+
{
3937+
has_used_file = true;
3938+
}
3939+
}
3940+
else
3941+
{
3942+
chosen_lang = {};
3943+
break;
3944+
}
3945+
}
3946+
}
3947+
}
3948+
3949+
if (chosen_lang.empty() || diff_pos == umax || !has_used_file)
3950+
{
3951+
// Failure
3952+
continue;
3953+
}
3954+
3955+
for (usz i = old_size, delete_at = umax; i < file_queue.size();)
3956+
{
3957+
if (delete_at != umax)
3958+
{
3959+
// Delete here to avoid UB
3960+
file_queue.erase(file_queue.begin() + delete_at);
3961+
delete_at = umax;
3962+
continue;
3963+
}
3964+
3965+
const std::string_view path = file_queue[i].path;
3966+
std::string fname = fmt::to_lower(path.substr(path.find_last_of(fs::delim) + 1));
3967+
3968+
if (prev_fname.size() == fname.size() && fname.ends_with(".self"))
3969+
{
3970+
usz j = 0;
3971+
3972+
for (; j < fname.size() - 7; j++)
3973+
{
3974+
if (prev_fname[j] != fname[j])
3975+
{
3976+
break;
3977+
}
3978+
}
3979+
3980+
if (j != diff_pos)
3981+
{
3982+
continue;
3983+
}
3984+
3985+
const std::string_view flang = std::string_view(fname).substr(j, 2);
3986+
3987+
if (s_ch_to_lang.contains(flang) && chosen_lang != flang)
3988+
{
3989+
// Not the file of the selected language, do not recompile it
3990+
delete_at = i;
3991+
continue;
3992+
}
3993+
}
3994+
3995+
i++;
3996+
}
3997+
}
38483998
}
38493999

38504000
g_progr_ftotal += ::size32(file_queue);
@@ -3854,6 +4004,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
38544004
for (const file_info& info : file_queue)
38554005
{
38564006
total_files_size += info.file_size;
4007+
4008+
if (!info.rec_name.empty())
4009+
{
4010+
ppu_log.notice("File to compile: '%s' of MSELF '%s' (size=0x%x)", info.rec_name, info.path, info.file_size);
4011+
}
4012+
else
4013+
{
4014+
ppu_log.notice("File to compile: '%s' (size=0x%x)", info.path, info.file_size);
4015+
}
38574016
}
38584017

38594018
g_progr_ftotal_bits += total_files_size;
@@ -3882,9 +4041,16 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
38824041
continue;
38834042
}
38844043

3885-
auto& [path, offset, file_size] = file_queue[func_i];
4044+
auto& [path, rec_name, offset, file_size] = file_queue[func_i];
38864045

3887-
ppu_log.notice("Trying to load: %s", path);
4046+
if (rec_name.empty())
4047+
{
4048+
ppu_log.notice("Trying to load: '%s'", path);
4049+
}
4050+
else
4051+
{
4052+
ppu_log.notice("Trying to load: '%s' ('%s')", path, rec_name);
4053+
}
38884054

38894055
// Load MSELF, SPRX or SELF
38904056
fs::file src{path};
@@ -4012,7 +4178,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
40124178
continue;
40134179
}
40144180

4015-
const auto& [path, _, file_size] = *slice;
4181+
const auto& [path, _x, _x2, file_size] = *slice;
40164182

40174183
ppu_log.notice("Trying to load as executable: %s", path);
40184184

0 commit comments

Comments
 (0)