From a41d2e43fdbe0cc233d0157c1f1064733000092b Mon Sep 17 00:00:00 2001 From: Eladash Date: Sat, 11 Mar 2023 08:55:22 +0200 Subject: [PATCH] cellFsReaddir: Fix termination sequence --- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 40 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.cpp b/rpcs3/Emu/Cell/lv2/sys_fs.cpp index 3f8aae22d2..5de98322ec 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_fs.cpp @@ -1337,10 +1337,14 @@ error_code sys_fs_opendir(ppu_thread& ppu, vm::cptr path, vm::ptr fd) error_code sys_fs_readdir(ppu_thread& ppu, u32 fd, vm::ptr dir, vm::ptr nread) { ppu.state += cpu_flag::wait; - lv2_obj::sleep(ppu); sys_fs.warning("sys_fs_readdir(fd=%d, dir=*0x%x, nread=*0x%x)", fd, dir, nread); + if (!dir || !nread) + { + return CELL_EFAULT; + } + const auto directory = idm::get(fd); if (!directory) @@ -1350,18 +1354,40 @@ error_code sys_fs_readdir(ppu_thread& ppu, u32 fd, vm::ptr dir, vm ppu.check_state(); - if (auto* info = directory->dir_read()) + auto* info = directory->dir_read(); + + u64 nread_to_write = 0; + + if (info) { - dir->d_type = info->is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR; - dir->d_namlen = u8(std::min(info->name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH)); - strcpy_trunc(dir->d_name, info->name); - *nread = sizeof(CellFsDirent); + nread_to_write = sizeof(CellFsDirent); } else { - *nread = 0; + // It does actually write polling the last entry. Seems consistent across HDD0 and HDD1 (TODO: check more partitions) + info = &directory->entries.back(); + nread_to_write = 0; } + CellFsDirent dir_write{}; + + dir_write.d_type = info->is_directory ? CELL_FS_TYPE_DIRECTORY : CELL_FS_TYPE_REGULAR; + dir_write.d_namlen = u8(std::min(info->name.size(), CELL_FS_MAX_FS_FILE_NAME_LENGTH)); + strcpy_trunc(dir_write.d_name, info->name); + + // TODO: Check more partitions (HDD1 is known to differ in actual filesystem implementation) + if (directory->mp != &g_mp_sys_dev_hdd1 && nread_to_write == 0) + { + // First 3 bytes are being set to 0 here + dir_write.d_type = 0; + dir_write.d_namlen = 0; + dir_write.d_name[0] = '\0'; + } + + *dir = dir_write; + + // Write after dir + *nread = nread_to_write; return CELL_OK; }