Loader: Improve just-in-time installation of disc game files (#10719)

* rsx: Indexed access to surface attributes
This commit is contained in:
Eladash 2021-08-19 08:49:59 +03:00 committed by GitHub
parent c13a46b07b
commit fcfeac818f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 79 deletions

View file

@ -1010,17 +1010,17 @@ namespace rsx
{
u32 offset_color[] =
{
rsx::method_registers.surface_a_offset(),
rsx::method_registers.surface_b_offset(),
rsx::method_registers.surface_c_offset(),
rsx::method_registers.surface_d_offset(),
rsx::method_registers.surface_offset(0),
rsx::method_registers.surface_offset(1),
rsx::method_registers.surface_offset(2),
rsx::method_registers.surface_offset(3),
};
u32 context_dma_color[] =
{
rsx::method_registers.surface_a_dma(),
rsx::method_registers.surface_b_dma(),
rsx::method_registers.surface_c_dma(),
rsx::method_registers.surface_d_dma(),
rsx::method_registers.surface_dma(0),
rsx::method_registers.surface_dma(1),
rsx::method_registers.surface_dma(2),
rsx::method_registers.surface_dma(3),
};
return
{
@ -1064,10 +1064,10 @@ namespace rsx
layout.zeta_pitch = rsx::method_registers.surface_z_pitch();
layout.color_pitch =
{
rsx::method_registers.surface_a_pitch(),
rsx::method_registers.surface_b_pitch(),
rsx::method_registers.surface_c_pitch(),
rsx::method_registers.surface_d_pitch(),
rsx::method_registers.surface_pitch(0),
rsx::method_registers.surface_pitch(1),
rsx::method_registers.surface_pitch(2),
rsx::method_registers.surface_pitch(3),
};
layout.color_format = rsx::method_registers.surface_color();

View file

@ -1106,64 +1106,37 @@ namespace rsx
return decode<NV4097_SET_SURFACE_CLIP_VERTICAL>().height();
}
u32 surface_a_offset() const
u32 surface_offset(u32 index) const
{
return decode<NV4097_SET_SURFACE_COLOR_AOFFSET>().surface_a_offset();
switch (index)
{
case 0: return decode<NV4097_SET_SURFACE_COLOR_AOFFSET>().surface_a_offset();
case 1: return decode<NV4097_SET_SURFACE_COLOR_BOFFSET>().surface_b_offset();
case 2: return decode<NV4097_SET_SURFACE_COLOR_COFFSET>().surface_c_offset();
default: return decode<NV4097_SET_SURFACE_COLOR_DOFFSET>().surface_d_offset();
}
}
u32 surface_b_offset() const
u32 surface_pitch(u32 index) const
{
return decode<NV4097_SET_SURFACE_COLOR_BOFFSET>().surface_b_offset();
switch (index)
{
case 0: return decode<NV4097_SET_SURFACE_PITCH_A>().surface_a_pitch();
case 1: return decode<NV4097_SET_SURFACE_PITCH_B>().surface_b_pitch();
case 2: return decode<NV4097_SET_SURFACE_PITCH_C>().surface_c_pitch();
default: return decode<NV4097_SET_SURFACE_PITCH_D>().surface_d_pitch();
}
}
u32 surface_c_offset() const
u32 surface_dma(u32 index) const
{
return decode<NV4097_SET_SURFACE_COLOR_COFFSET>().surface_c_offset();
}
u32 surface_d_offset() const
{
return decode<NV4097_SET_SURFACE_COLOR_DOFFSET>().surface_d_offset();
}
u32 surface_a_pitch() const
{
return decode<NV4097_SET_SURFACE_PITCH_A>().surface_a_pitch();
}
u32 surface_b_pitch() const
{
return decode<NV4097_SET_SURFACE_PITCH_B>().surface_b_pitch();
}
u32 surface_c_pitch() const
{
return decode<NV4097_SET_SURFACE_PITCH_C>().surface_c_pitch();
}
u32 surface_d_pitch() const
{
return decode<NV4097_SET_SURFACE_PITCH_D>().surface_d_pitch();
}
u32 surface_a_dma() const
{
return decode<NV4097_SET_CONTEXT_DMA_COLOR_A>().dma_surface_a();
}
u32 surface_b_dma() const
{
return decode<NV4097_SET_CONTEXT_DMA_COLOR_B>().dma_surface_b();
}
u32 surface_c_dma() const
{
return decode<NV4097_SET_CONTEXT_DMA_COLOR_C>().dma_surface_c();
}
u32 surface_d_dma() const
{
return decode<NV4097_SET_CONTEXT_DMA_COLOR_D>().dma_surface_d();
switch (index)
{
case 0: return decode<NV4097_SET_CONTEXT_DMA_COLOR_A>().dma_surface_a();
case 1: return decode<NV4097_SET_CONTEXT_DMA_COLOR_B>().dma_surface_b();
case 2: return decode<NV4097_SET_CONTEXT_DMA_COLOR_C>().dma_surface_c();
default: return decode<NV4097_SET_CONTEXT_DMA_COLOR_D>().dma_surface_d();
}
}
u32 surface_z_offset() const

View file

@ -205,7 +205,7 @@ void Emulator::Init(bool add_only)
make_path_verbose(dev_hdd0 + "game/");
make_path_verbose(dev_hdd0 + "game/TEST12345/");
make_path_verbose(dev_hdd0 + "game/TEST12345/USRDIR/");
make_path_verbose(dev_hdd0 + "game/.locks/");
make_path_verbose(dev_hdd0 + reinterpret_cast<const char*>(u8"game/locks/"));
make_path_verbose(dev_hdd0 + "home/");
make_path_verbose(dev_hdd0 + "home/" + m_usr + "/");
make_path_verbose(dev_hdd0 + "home/" + m_usr + "/exdata/");
@ -1015,21 +1015,40 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
return game_boot_result::no_errors;
}
// Set title to actual disc title if necessary
const std::string disc_sfo_dir = vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO");
const auto disc_psf_obj = psf::load_object(fs::file{ disc_sfo_dir });
// Install PKGDIR, INSDIR, PS3_EXTRA
if (!bdvd_dir.empty())
{
const std::string ins_dir = vfs::get("/dev_bdvd/PS3_GAME/INSDIR/");
const std::string pkg_dir = vfs::get("/dev_bdvd/PS3_GAME/PKGDIR/");
const std::string extra_dir = vfs::get("/dev_bdvd/PS3_GAME/PS3_EXTRA/");
std::string ins_dir = vfs::get("/dev_bdvd/PS3_GAME/INSDIR/");
std::string pkg_dir = vfs::get("/dev_bdvd/PS3_GAME/PKGDIR/");
std::string extra_dir = vfs::get("/dev_bdvd/PS3_GAME/PS3_EXTRA/");
fs::file lock_file;
if (fs::is_dir(ins_dir) || fs::is_dir(pkg_dir) || fs::is_dir(extra_dir))
for (const auto path_ptr : {&ins_dir, &pkg_dir, &extra_dir})
{
// Create lock file to prevent double installation
lock_file.open(hdd0_game + ".locks/" + m_title_id, fs::read + fs::create + fs::excl);
if (!fs::is_dir(*path_ptr))
{
path_ptr->clear();
}
}
if (lock_file && fs::is_dir(ins_dir))
const std::string lock_file_path = fmt::format("%s%s%s_v%s", hdd0_game, u8"locks/", m_title_id, psf::get_string(disc_psf_obj, "APP_VER"));
if (!ins_dir.empty() || !pkg_dir.empty() || !extra_dir.empty())
{
// For backwards compatibility
if (!lock_file.open(hdd0_game + ".locks/" + m_title_id))
{
// Check if already installed
lock_file.open(lock_file_path);
}
}
if (!lock_file && !ins_dir.empty())
{
sys_log.notice("Found INSDIR: %s", ins_dir);
@ -1044,7 +1063,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
}
if (lock_file && fs::is_dir(pkg_dir))
if (!lock_file && !pkg_dir.empty())
{
sys_log.notice("Found PKGDIR: %s", pkg_dir);
@ -1063,7 +1082,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
}
if (lock_file && fs::is_dir(extra_dir))
if (!lock_file && !extra_dir.empty())
{
sys_log.notice("Found PS3_EXTRA: %s", extra_dir);
@ -1081,6 +1100,13 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
}
}
if (!lock_file)
{
// Create lock file to prevent double installation
// Do it after installation to prevent false positives when RPCS3 closed in the middle of the operation
lock_file.open(lock_file_path, fs::read + fs::create + fs::excl);
}
}
// Check game updates
@ -1093,13 +1119,9 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
return m_path = hdd0_boot, Load(m_title_id, false, force_global_config, true);
}
// Set title to actual disc title if necessary
const std::string disc_sfo_dir = vfs::get("/dev_bdvd/PS3_GAME/PARAM.SFO");
if (!disc_sfo_dir.empty() && fs::is_file(disc_sfo_dir))
if (!disc_psf_obj.empty())
{
const auto psf_obj = psf::load_object(fs::file{ disc_sfo_dir });
const auto bdvd_title = psf::get_string(psf_obj, "TITLE");
const auto bdvd_title = psf::get_string(disc_psf_obj, "TITLE");
if (!bdvd_title.empty() && bdvd_title != m_title)
{