From fc14a8a7072f367b9d1f19b1624f57cc576376e3 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 7 Nov 2023 11:04:59 +0200 Subject: [PATCH] sceKernelGetdents implementation --- src/common/fs_file.cpp | 20 ++++++++--- src/core/PS4/HLE/Graphics/video_out.cpp | 28 ++++++++------- src/core/file_sys/fs.h | 4 +-- .../hle/libraries/libkernel/file_system.cpp | 34 ++++++++++++++++--- .../hle/libraries/libkernel/file_system.h | 11 ++++++ 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/src/common/fs_file.cpp b/src/common/fs_file.cpp index 8c535ae4..980ce126 100644 --- a/src/common/fs_file.cpp +++ b/src/common/fs_file.cpp @@ -59,13 +59,25 @@ u64 File::tell() const { } std::vector File::getDirectoryEntries(const std::string& path) { + std::string curpath = path; + if (!curpath.ends_with("/")) + { + curpath = std::string(curpath + "/"); + } std::vector < DirEntry> files; - for (const auto& entry : std::filesystem::directory_iterator(path)) { - if (std::filesystem::is_regular_file(path)) { - + for (const auto& entry : std::filesystem::directory_iterator(curpath)) { + if (std::filesystem::is_regular_file( entry.path().string())) { + DirEntry e = {}; + e.name = entry.path().filename().string(); + e.isFile = true; + files.push_back(e); + } else { + DirEntry e = {}; + e.name = entry.path().filename().string() + "/"; //hmmm not sure if it has to be like this... + e.isFile = false; + files.push_back(e); } - //entry.path() } return files; diff --git a/src/core/PS4/HLE/Graphics/video_out.cpp b/src/core/PS4/HLE/Graphics/video_out.cpp index c87c1a87..79ee421e 100644 --- a/src/core/PS4/HLE/Graphics/video_out.cpp +++ b/src/core/PS4/HLE/Graphics/video_out.cpp @@ -1,19 +1,21 @@ -#include -#include -#include -#include "common/log.h" -#include "common/debug.h" -#include "core/loader/symbols_resolver.h" #include "core/PS4/HLE/Graphics/video_out.h" + +#include +#include +#include + +#include "Objects/video_out_ctx.h" +#include "Util/config.h" +#include "common/debug.h" +#include "common/log.h" +#include "common/singleton.h" #include "core/PS4/GPU/gpu_memory.h" #include "core/PS4/GPU/video_out_buffer.h" #include "core/hle/error_codes.h" -#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h" #include "core/hle/libraries/libs.h" +#include "core/hle/libraries/libscegnmdriver/libscegnmdriver.h" #include "core/hle/libraries/libuserservice/usr_mng_codes.h" -#include "Util/config.h" -#include "Objects/video_out_ctx.h" -#include "common/singleton.h" +#include "core/loader/symbols_resolver.h" #include "emulator.h" #include "graphics_render.h" @@ -222,7 +224,7 @@ s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate) { } s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle) { - PRINT_FUNCTION_NAME(); + // PRINT_FUNCTION_NAME(); auto* videoOut = Common::Singleton::Instance(); s32 pending = videoOut->getCtx(handle)->m_flip_status.flipPendingNum; return pending; @@ -234,8 +236,8 @@ s32 PS4_SYSV_ABI sceVideoOutSubmitFlip(s32 handle, s32 bufferIndex, s32 flipMode auto* ctx = videoOut->getCtx(handle); if (flipMode != 1) { - // BREAKPOINT(); // only flipmode==1 is supported - LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flipmode {}\n", bufferIndex);//openBOR needs 2 but seems to work + // BREAKPOINT(); // only flipmode==1 is supported + LOG_TRACE_IF(log_file_videoout, "sceVideoOutSubmitFlip flipmode {}\n", bufferIndex); // openBOR needs 2 but seems to work } if (bufferIndex == -1) { BREAKPOINT(); // blank output not supported diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 1254988e..414d8281 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -32,8 +32,8 @@ struct File { std::string m_host_name; std::string m_guest_name; Common::FS::File f; - std::vector dents; - u32 dents_index; + std::vector dirents; + u32 dirents_index; }; class HandleTable { public: diff --git a/src/core/hle/libraries/libkernel/file_system.cpp b/src/core/hle/libraries/libkernel/file_system.cpp index 24587714..7d11121b 100644 --- a/src/core/hle/libraries/libkernel/file_system.cpp +++ b/src/core/hle/libraries/libkernel/file_system.cpp @@ -40,8 +40,8 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { return SCE_KERNEL_ERROR_ENOTDIR; } return SCE_KERNEL_ERROR_ENOTDIR;*/ - //there is seems to be a bug with create_directories return false even if the directory creates so don't check until we find - //a better solution + // there is seems to be a bug with create_directories return false even if the directory creates so don't check until we find + // a better solution std::filesystem::create_directories(file->m_host_name); return handle; } @@ -49,11 +49,12 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { if (create) { return handle; // directory already exists } else { - BREAKPOINT(); // here we should handle open directory mode + file->dirents = Common::FS::File::getDirectoryEntries(file->m_host_name); + file->dirents_index = 0; } } } - + file->isOpened = true; return handle; } @@ -66,6 +67,30 @@ int PS4_SYSV_ABI sceKernelClose(int handle) { return SCE_OK; } +int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) { + PRINT_FUNCTION_NAME(); + //TODO error codes + auto* h = Common::Singleton::Instance(); + auto* file = h->getFile(fd); + + if (file->dirents_index == file->dirents.size()) { + return 0; + } + + const auto& entry = file->dirents.at(file->dirents_index++); + auto str = entry.name; + auto str_size = str.size() - 1; + + SceKernelDirent* sce_ent = (SceKernelDirent*)buf; + sce_ent->d_fileno = fd; //TODO this should be unique but atm it changes maybe switch to a hash or something? + sce_ent->d_reclen = sizeof(SceKernelDirent); + sce_ent->d_type = (entry.isFile ? 8 : 4); + sce_ent->d_namlen = str_size; + strcpy_s(sce_ent->d_name, SCE_MAX_PATH, str.data()); + + return sizeof(SceKernelDirent); +} + int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { LOG_INFO_IF(log_file_fs, "posix open redirect to sceKernelOpen\n"); int result = sceKernelOpen(path, flags, mode); @@ -78,6 +103,7 @@ int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 void fileSystemSymbolsRegister(Loader::SymbolsResolver* sym) { LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen); LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose); + LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); } diff --git a/src/core/hle/libraries/libkernel/file_system.h b/src/core/hle/libraries/libkernel/file_system.h index 277be463..08d14d0f 100644 --- a/src/core/hle/libraries/libkernel/file_system.h +++ b/src/core/hle/libraries/libkernel/file_system.h @@ -7,6 +7,16 @@ class SymbolsResolver; } namespace Core::Libraries::LibKernel { +constexpr int SCE_MAX_PATH = 255; + +struct SceKernelDirent { + uint32_t d_fileno; /* file number of entry */ + uint16_t d_reclen; /* length of this record */ + uint8_t d_type; /* file type, see below */ + uint8_t d_namlen; /* length of string in d_name */ + char d_name[SCE_MAX_PATH + 1]; /* name must be no longer than this */ +}; + // open flags constexpr u32 SCE_KERNEL_O_RDONLY = 0x0000; // Open as read-only constexpr u32 SCE_KERNEL_O_WRONLY = 0x0001; // Open as write-only @@ -24,6 +34,7 @@ constexpr u32 SCE_KERNEL_O_DIRECTORY = 0x00020000; // Error will occur if not a int PS4_SYSV_ABI sceKernelOpen(const char *path, int flags, /* SceKernelMode*/ u16 mode); int PS4_SYSV_ABI sceKernelClose(int handle); +int PS4_SYSV_ABI sceKernelGetdents(int fd, char *buf, int nbytes); int PS4_SYSV_ABI posix_open(const char *path, int flags, /* SceKernelMode*/ u16 mode); void fileSystemSymbolsRegister(Loader::SymbolsResolver *sym);