diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 6e202edcdf..c6cfd1cb78 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -22,15 +22,15 @@ LOG_CHANNEL(sys_fs); lv2_fs_mount_point g_mp_sys_dev_root; lv2_fs_mount_point g_mp_sys_no_device; -lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0"}; -lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", 512, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache}; -lv2_fs_mount_point g_mp_sys_dev_usb{"", 512, 4096, lv2_mp_flag::no_uid_gid}; -lv2_fs_mount_point g_mp_sys_dev_bdvd{"", 2048, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; -lv2_fs_mount_point g_mp_sys_dev_dvd{"", 2048, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; -lv2_fs_mount_point g_mp_sys_host_root{"", 512, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid}; -lv2_fs_mount_point g_mp_sys_dev_flash{"", 512, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; -lv2_fs_mount_point g_mp_sys_dev_flash2{ "", 512, 8192, lv2_mp_flag::no_uid_gid }; // TODO confirm -lv2_fs_mount_point g_mp_sys_dev_flash3{ "", 512, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid }; // TODO confirm +lv2_fs_mount_point g_mp_sys_dev_hdd0{"/dev_hdd0", 512, 0x24FAEA98}; +lv2_fs_mount_point g_mp_sys_dev_hdd1{"/dev_hdd1", 512, 0x3FFFF8, 32768, lv2_mp_flag::no_uid_gid + lv2_mp_flag::cache}; +lv2_fs_mount_point g_mp_sys_dev_usb{"", 512, 0x100, 4096, lv2_mp_flag::no_uid_gid}; +lv2_fs_mount_point g_mp_sys_dev_bdvd{"", 2048, 0x4D955, 65536, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; +lv2_fs_mount_point g_mp_sys_dev_dvd{"", 2048, 0x100, 32768, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; +lv2_fs_mount_point g_mp_sys_host_root{"", 512, 0x100, 512, lv2_mp_flag::strict_get_block_size + lv2_mp_flag::no_uid_gid}; +lv2_fs_mount_point g_mp_sys_dev_flash{"", 512, 0x63E00, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; +lv2_fs_mount_point g_mp_sys_dev_flash2{"", 512, 0x8000, 8192, lv2_mp_flag::no_uid_gid}; // TODO confirm +lv2_fs_mount_point g_mp_sys_dev_flash3{"", 512, 0x400, 8192, lv2_mp_flag::read_only + lv2_mp_flag::no_uid_gid}; // TODO confirm template<> void fmt_class_string::format(std::string& out, u64 arg) @@ -524,7 +524,7 @@ fs::file lv2_file::make_view(const std::shared_ptr& _file, u64 offset) return result; } -std::pair translate_to_sv(vm::cptr ptr) +std::pair translate_to_sv(vm::cptr ptr, bool is_path = true) { const u32 addr = ptr.addr(); @@ -553,7 +553,7 @@ std::pair translate_to_sv(vm::cptr ptr) return {CELL_EFAULT, path}; } - if (!path.starts_with("/"sv)) + if (is_path && !path.starts_with("/"sv)) { return {CELL_ENOENT, path}; } @@ -3008,17 +3008,52 @@ error_code sys_fs_mount(ppu_thread&, vm::cptr dev_name, vm::cptr fil return { path_error, vpath }; } + const auto [fs_error, filesystem] = translate_to_sv(file_system, false); + + if (fs_error) + { + return { fs_error, filesystem }; + } + const auto mp = lv2_fs_object::get_mp(vpath); bool success = true; + auto vfs_mount = [&](std::string mount_path) + { + const u64 file_size = filesystem == "CELL_FS_SIMPLEFS" ? mp->sector_size * mp->sector_count : 0; + if (!mount_path.ends_with('/')) + mount_path += '/'; + if (!fs::is_dir(mount_path) && !fs::create_dir(mount_path)) + { + sys_fs.error("Failed to create directory \"%s\"", mount_path); + return false; + } + if (file_size > 0) + { + mount_path += "loop.tmp"; + fs::file loop_file; + if (loop_file.open(mount_path, fs::create + fs::read + fs::write + fs::trunc + fs::lock)) + { + loop_file.trunc(file_size); + sys_fs.notice("Created a loop file of size %d at \"%s\"", file_size, mount_path); + } + else + { + sys_fs.error("Failed to create loop file \"%s\"", mount_path); + return false; + } + } + return vfs::mount(vpath, mount_path, file_size == 0); + }; + if (mp == &g_mp_sys_dev_hdd1) { const std::string_view appname = g_ps3_process_info.get_cellos_appname(); - success = vfs::mount(vpath, fmt::format("%s/caches/%s", lv2_fs_object::get_vfs(vpath), appname.substr(0, appname.find_last_of('.'))), true); + success = vfs_mount(fmt::format("%s/caches/%s", lv2_fs_object::get_vfs(vpath), appname.substr(0, appname.find_last_of('.')))); } else { - //success = vfs::mount(vpath, lv2_fs_object::get_vfs(vpath)); // We are not supporting mounting devices other than /dev_hdd1 via this syscall currently + //success = vfs_mount(lv2_fs_object::get_vfs(vpath)); // We are not supporting mounting devices other than /dev_hdd1 via this syscall currently } if (!success) @@ -3043,9 +3078,29 @@ error_code sys_fs_unmount(ppu_thread&, vm::cptr path, s32 unk1, s32 unk2) return { path_error, vpath }; } + const auto mp = lv2_fs_object::get_mp(vpath); bool success = true; - //success = vfs::unmount(vpath); // Not really unmounting it at the moment + auto vfs_unmount = [&]() + { + const std::string local_path = vfs::get(vpath); + if (fs::is_file(local_path)) + { + if (fs::remove_file(local_path)) + { + sys_fs.notice("Removed loop file \"%s\"", local_path); + } + else + { + sys_fs.error("Failed to remove loop file \"%s\"", local_path); + return false; + } + } + return vfs::unmount(vpath); + }; + + if (mp == &g_mp_sys_dev_hdd1) // We are not supporting unmounting devices other than /dev_hdd1 via this syscall currently + success = vfs_unmount(); if (!success) return CELL_EIO; diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index b9c21f7a40..2f51b9280e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -149,6 +149,7 @@ struct lv2_fs_mount_point { const std::string_view root; const u32 sector_size = 512; + const u64 sector_count = 256; const u32 block_size = 4096; const bs_t flags{}; diff --git a/rpcs3/Emu/VFS.cpp b/rpcs3/Emu/VFS.cpp index 5b47d36d3f..3e472793f8 100644 --- a/rpcs3/Emu/VFS.cpp +++ b/rpcs3/Emu/VFS.cpp @@ -33,7 +33,7 @@ struct vfs_manager vfs_directory root{}; }; -bool vfs::mount(std::string_view vpath, std::string_view path, bool create_dir, bool is_dir) +bool vfs::mount(std::string_view vpath, std::string_view path, bool is_dir) { if (vpath.empty()) { @@ -42,12 +42,6 @@ bool vfs::mount(std::string_view vpath, std::string_view path, bool create_dir, return false; } - if (create_dir && !fs::is_dir(std::string(path)) && !fs::create_dir(std::string(path))) - { - vfs_log.error("Cannot create directory \"%s\"", path); - return false; - } - // Workaround g_fxo->need(); diff --git a/rpcs3/Emu/VFS.h b/rpcs3/Emu/VFS.h index b943053b00..0f69a2b697 100644 --- a/rpcs3/Emu/VFS.h +++ b/rpcs3/Emu/VFS.h @@ -10,7 +10,7 @@ struct vfs_directory; namespace vfs { // Mount VFS device - bool mount(std::string_view vpath, std::string_view path, bool create_dir = false, bool is_dir = true); + bool mount(std::string_view vpath, std::string_view path, bool is_dir = true); // Unmount VFS device bool unmount(std::string_view vpath);