21
21
#include " PPUDisAsm.h"
22
22
#include " SPURecompiler.h"
23
23
#include " timers.hpp"
24
+ #include " Emu/Cell/Modules/cellSysutil.h"
24
25
#include " lv2/sys_sync.h"
25
26
#include " lv2/sys_prx.h"
26
27
#include " lv2/sys_overlay.h"
@@ -3675,13 +3676,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3675
3676
struct file_info
3676
3677
{
3677
3678
std::string path;
3679
+ std::string rec_name;
3678
3680
u64 offset;
3679
3681
u64 file_size;
3680
3682
3681
3683
file_info () noexcept = default ;
3682
3684
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
3684
3686
: path(std::move(_path))
3687
+ , rec_name(std::move(_rec))
3685
3688
, offset(offs)
3686
3689
, file_size(size)
3687
3690
{
@@ -3702,6 +3705,8 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3702
3705
3703
3706
ppu_log.notice (" Scanning directory: %s" , dir_queue[i]);
3704
3707
3708
+ const usz old_size = file_queue.size ();
3709
+
3705
3710
for (auto && entry : fs::dir (dir_queue[i]))
3706
3711
{
3707
3712
if (Emu.IsStopped ())
@@ -3773,15 +3778,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3773
3778
}
3774
3779
3775
3780
// 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 );
3777
3782
continue ;
3778
3783
}
3779
3784
3780
3785
// Check ELF filename
3781
3786
if ((upper.ends_with (" .ELF" ) || upper.ends_with (" .SELF" )) && Emu.GetBoot () != dir_queue[i] + entry.name )
3782
3787
{
3783
3788
// 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 );
3785
3790
continue ;
3786
3791
}
3787
3792
@@ -3824,14 +3829,14 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3824
3829
if (upper.find (" .SPRX" ) != umax || upper.find (" .PRX" ) != umax)
3825
3830
{
3826
3831
// .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 );
3828
3833
continue ;
3829
3834
}
3830
3835
3831
3836
if (upper.find (" .SELF" ) != umax || upper.find (" .ELF" ) != umax)
3832
3837
{
3833
3838
// .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 );
3835
3840
continue ;
3836
3841
}
3837
3842
}
@@ -3845,6 +3850,151 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3845
3850
}
3846
3851
}
3847
3852
}
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
+ }
3848
3998
}
3849
3999
3850
4000
g_progr_ftotal += ::size32 (file_queue);
@@ -3854,6 +4004,15 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3854
4004
for (const file_info& info : file_queue)
3855
4005
{
3856
4006
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
+ }
3857
4016
}
3858
4017
3859
4018
g_progr_ftotal_bits += total_files_size;
@@ -3882,9 +4041,16 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
3882
4041
continue ;
3883
4042
}
3884
4043
3885
- auto & [path, offset, file_size] = file_queue[func_i];
4044
+ auto & [path, rec_name, offset, file_size] = file_queue[func_i];
3886
4045
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
+ }
3888
4054
3889
4055
// Load MSELF, SPRX or SELF
3890
4056
fs::file src{path};
@@ -4012,7 +4178,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
4012
4178
continue ;
4013
4179
}
4014
4180
4015
- const auto & [path, _ , file_size] = *slice;
4181
+ const auto & [path, _x, _x2 , file_size] = *slice;
4016
4182
4017
4183
ppu_log.notice (" Trying to load as executable: %s" , path);
4018
4184
0 commit comments