diff --git a/rpcs3/Crypto/unedat.h b/rpcs3/Crypto/unedat.h index 0bde5e7104db..94788e497fd9 100644 --- a/rpcs3/Crypto/unedat.h +++ b/rpcs3/Crypto/unedat.h @@ -18,6 +18,7 @@ struct loaded_npdrm_keys { std::array devKlic{}; std::array rifKey{}; + atomic_t npdrm_fds{0}; }; struct NPD_HEADER diff --git a/rpcs3/Emu/Cell/Modules/cellFs.cpp b/rpcs3/Emu/Cell/Modules/cellFs.cpp index e3c608bfc6a4..6923116f976a 100644 --- a/rpcs3/Emu/Cell/Modules/cellFs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellFs.cpp @@ -863,12 +863,6 @@ s32 cellFsStReadWaitCallback(u32 fd, u64 size, vm::ptr using fs_aio_cb_t = vm::ptr xaio, s32 error, s32 xid, u64 size)>; -// temporarily -struct lv2_fs_mount_point -{ - std::mutex mutex; -}; - struct fs_aio_thread : ppu_thread { using ppu_thread::ppu_thread; diff --git a/rpcs3/Emu/Cell/Modules/cellSysCache.cpp b/rpcs3/Emu/Cell/Modules/cellSysCache.cpp index 157a566b2fd3..7f2f3078bfea 100644 --- a/rpcs3/Emu/Cell/Modules/cellSysCache.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSysCache.cpp @@ -28,6 +28,8 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +extern lv2_fs_mount_point g_mp_sys_dev_hdd1; + struct syscache_info { const std::string cache_root = Emu.GetHdd1Dir() + "/caches/"; @@ -77,6 +79,8 @@ struct syscache_info // Poison opened files in /dev_hdd1 to return CELL_EIO on access if (remove_root) { + std::lock_guard lock(g_mp_sys_dev_hdd1.mutex); + idm::select([](u32 id, lv2_file& file) { if (std::memcmp("/dev_hdd1", file.name.data(), 9) == 0) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index d901ed7ec11e..5dff9548414d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -10,15 +10,6 @@ LOG_CHANNEL(sys_fs); -struct lv2_fs_mount_point -{ - const u32 sector_size = 512; - const u32 block_size = 4096; - const bs_t flags{}; - - shared_mutex mutex; -}; - lv2_fs_mount_point g_mp_sys_dev_hdd0; lv2_fs_mount_point g_mp_sys_dev_hdd1{512, 32768, lv2_mp_flag::no_uid_gid}; lv2_fs_mount_point g_mp_sys_dev_usb{512, 4096, lv2_mp_flag::no_uid_gid}; @@ -485,7 +476,42 @@ error_code sys_fs_open(ppu_thread& ppu, vm::cptr path, s32 flags, vm::ptr< return {error, path}; } - if (const u32 id = idm::make(ppath, std::move(file), mode, flags)) + lv2_file_type type = lv2_file_type::regular; + + if (size == 8) + { + // see lv2_file::open + switch (vm::read64(arg.addr())) + { + case 0x18000000010: + case 0x2: + { + type = lv2_file_type::npdrm; + sys_fs.warning("sys_fs_open(): NPDRM detected"); + break; + } + default: + break; + } + } + + if (type == lv2_file_type::npdrm) + { + if (const u32 id = idm::import([&ppath = ppath, &file = file, mode, flags]() -> std::shared_ptr + { + if (!g_fxo->get()->npdrm_fds.try_inc(16)) + { + return nullptr; + } + + return std::make_shared(ppath, std::move(file), mode, flags, lv2_file_type::npdrm); + })) + { + *fd = id; + return CELL_OK; + } + } + else if (const u32 id = idm::make(ppath, std::move(file), mode, flags)) { *fd = id; return CELL_OK; @@ -594,7 +620,13 @@ error_code sys_fs_close(ppu_thread& ppu, u32 fd) sys_fs.trace("sys_fs_close(fd=%d)", fd); - const auto file = idm::withdraw(fd); + const auto file = idm::withdraw(fd, [](lv2_file& file) + { + if (file.type == lv2_file_type::npdrm) + { + g_fxo->get()->npdrm_fds--; + } + }); if (!file) { @@ -1236,7 +1268,15 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr _arg, u32 fs::file stream; stream.reset(std::move(sdata_file)); - if (const u32 id = idm::make(*file, std::move(stream), file->mode, file->flags)) + if (const u32 id = idm::import([&file = *file, &stream = stream]() -> std::shared_ptr + { + if (!g_fxo->get()->npdrm_fds.try_inc(16)) + { + return nullptr; + } + + return std::make_shared(file, std::move(stream), file.mode, file.flags, lv2_file_type::npdrm); + })) { arg->out_code = CELL_OK; arg->out_fd = id; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index d62cd39edaf6..da38317644c7 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -3,6 +3,7 @@ #include "Emu/Memory/vm_ptr.h" #include "Emu/Cell/ErrorCodes.h" #include "Utilities/File.h" +#include "Utilities/mutex.h" #include @@ -121,8 +122,6 @@ struct FsMselfEntry u8 m_reserve[16]; }; -struct lv2_fs_mount_point; - enum class lv2_mp_flag { read_only, @@ -132,6 +131,21 @@ enum class lv2_mp_flag __bitset_enum_max }; +enum class lv2_file_type +{ + regular = 0, + npdrm, +}; + +struct lv2_fs_mount_point +{ + const u32 sector_size = 512; + const u32 block_size = 4096; + const bs_t flags{}; + + shared_mutex mutex; +}; + struct lv2_fs_object { using id_type = lv2_fs_object; @@ -174,23 +188,26 @@ struct lv2_file final : lv2_fs_object const fs::file file; const s32 mode; const s32 flags; + const lv2_file_type type; // Stream lock atomic_t lock{0}; - lv2_file(std::string_view filename, fs::file&& file, s32 mode, s32 flags) + lv2_file(std::string_view filename, fs::file&& file, s32 mode, s32 flags, lv2_file_type type = {}) : lv2_fs_object(lv2_fs_object::get_mp(filename), filename) , file(std::move(file)) , mode(mode) , flags(flags) + , type(type) { } - lv2_file(const lv2_file& host, fs::file&& file, s32 mode, s32 flags) + lv2_file(const lv2_file& host, fs::file&& file, s32 mode, s32 flags, lv2_file_type type = {}) : lv2_fs_object(host.mp, host.name.data()) , file(std::move(file)) , mode(mode) , flags(flags) + , type(type) { }