diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index 6a99a808..912c74bf 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -28,15 +28,13 @@ void MntPoints::UnmountAll() { std::string MntPoints::GetHostDirectory(const std::string& guest_directory) { std::scoped_lock lock{m_mutex}; for (auto& pair : m_mnt_pairs) { - if (pair.guest_path.starts_with(guest_directory)) { - return pair.host_path + guest_directory; - } - } - // hack for relative path , get app0 and assuming it goes from there - for (auto& pair : m_mnt_pairs) { - if (pair.guest_path.starts_with("/app0")) { + // horrible code but it works :D + int find = guest_directory.find(pair.guest_path); + if (find == 0) { + std::string npath = + guest_directory.substr(pair.guest_path.size(), guest_directory.size() - 1); std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/'); - return pair.host_path + guest_directory; + return pair.host_path + npath; } } return ""; @@ -97,4 +95,5 @@ File* HandleTable::getFile(const std::string& host_name) { } return nullptr; } + } // namespace Core::FileSys diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 7d7b9985..4ba01685 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -32,13 +32,18 @@ private: std::mutex m_mutex; }; +struct DirEntry { + std::string name; + bool isFile; +}; + struct File { std::atomic_bool is_opened{}; std::atomic_bool is_directory{}; std::string m_host_name; std::string m_guest_name; Common::FS::IOFile f; - // std::vector dirents; + std::vector dirents; u32 dirents_index; std::mutex m_mutex; }; diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 5357f69c..f2795214 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -11,6 +11,29 @@ namespace Libraries::Kernel { +std::vector GetDirectoryEntries(const std::string& path) { + std::string curpath = path; + if (!curpath.ends_with("/")) { + curpath = std::string(curpath + "/"); + } + std::vector files; + + for (const auto& entry : std::filesystem::directory_iterator(curpath)) { + Core::FileSys::DirEntry e = {}; + if (std::filesystem::is_regular_file(entry.path().string())) { + e.name = entry.path().filename().string(); + e.isFile = true; + } else { + Core::FileSys::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); + } + + return files; +} int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { LOG_INFO(Kernel_Fs, "path = {} flags = {:#x} mode = {}", path, flags, mode); auto* h = Common::Singleton::Instance(); @@ -31,11 +54,23 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0; bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0; + u32 handle = h->CreateHandle(); + auto* file = h->GetFile(handle); if (directory) { - UNREACHABLE(); // not supported yet + file->is_directory = true; + file->m_guest_name = path; + file->m_host_name = mnt->GetHostDirectory(file->m_guest_name); + if (!std::filesystem::is_directory(file->m_host_name)) { // directory doesn't exist + UNREACHABLE(); // not supported yet + } else { + if (create) { + return handle; // dir already exists + } else { + file->dirents = GetDirectoryEntries(file->m_host_name); + file->dirents_index = 0; + } + } } else { - u32 handle = h->CreateHandle(); - auto* file = h->GetFile(handle); file->m_guest_name = path; file->m_host_name = mnt->GetHostFile(file->m_guest_name); if (read) { @@ -57,10 +92,62 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { h->DeleteHandle(handle); return SCE_KERNEL_ERROR_EACCES; } - file->is_opened = true; - return handle; } - return -1; // dummy + file->is_opened = true; + return handle; +} + +int PS4_SYSV_ABI sceKernelGetdents(int fd, char* buf, int nbytes) { + // 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; + static int fileno = 1000; // random + OrbisKernelDirent* sce_ent = (OrbisKernelDirent*)buf; + sce_ent->d_fileno = fileno++; // TODO this should be unique but atm it changes maybe switch to a + // hash or something? + sce_ent->d_reclen = sizeof(OrbisKernelDirent); + sce_ent->d_type = (entry.isFile ? 8 : 4); + sce_ent->d_namlen = str_size; + strncpy(sce_ent->d_name, str.c_str(), ORBIS_MAX_PATH); + sce_ent->d_name[ORBIS_MAX_PATH] = '\0'; + + return sizeof(OrbisKernelDirent); +} + +int PS4_SYSV_ABI sceKernelGetdirentries(int fd, char* buf, int nbytes, s64* basep) { + // TODO error codes + auto* h = Common::Singleton::Instance(); + auto* file = h->GetFile(fd); + if (basep != nullptr) { + *basep = file->dirents_index; + } + + 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; + static int fileno = 1000; // random + OrbisKernelDirent* sce_ent = (OrbisKernelDirent*)buf; + sce_ent->d_fileno = fileno++; // TODO this should be unique but atm it changes maybe switch to a + // hash or something? + sce_ent->d_reclen = sizeof(OrbisKernelDirent); + sce_ent->d_type = (entry.isFile ? 8 : 4); + sce_ent->d_namlen = str_size; + strncpy(sce_ent->d_name, str.c_str(), ORBIS_MAX_PATH); + sce_ent->d_name[ORBIS_MAX_PATH] = '\0'; + + return sizeof(OrbisKernelDirent); } int PS4_SYSV_ABI posix_open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { @@ -277,6 +364,9 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("1-LFLmRFxxM", "libkernel", 1, "libkernel", 1, 1, sceKernelMkdir); LIB_FUNCTION("eV9wAD2riIA", "libkernel", 1, "libkernel", 1, 1, sceKernelStat); LIB_FUNCTION("kBwCPsYX-m4", "libkernel", 1, "libkernel", 1, 1, sceKernelFStat); + LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents); + LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries); + LIB_FUNCTION("E6ao34wPw+U", "libScePosix", 1, "libkernel", 1, 1, posix_stat); LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread); diff --git a/src/core/libraries/kernel/file_system.h b/src/core/libraries/kernel/file_system.h index 865f1b05..0738456e 100644 --- a/src/core/libraries/kernel/file_system.h +++ b/src/core/libraries/kernel/file_system.h @@ -12,6 +12,8 @@ class SymbolsResolver; namespace Libraries::Kernel { +constexpr int ORBIS_MAX_PATH = 255; + struct SceKernelIovec { void* iov_base; std::size_t iov_len; @@ -39,6 +41,14 @@ struct OrbisKernelStat { unsigned int : (8 / 2) * (16 - static_cast(sizeof(SceKernelTimespec))); }; +struct OrbisKernelDirent { + u32 d_fileno; /* file number of entry */ + u16 d_reclen; /* length of this record */ + u8 d_type; /* file type, see below */ + u8 d_namlen; /* length of string in d_name */ + char d_name[ORBIS_MAX_PATH + 1]; /* name must be no longer than this */ +}; + // flags for Open constexpr int ORBIS_KERNEL_O_RDONLY = 0x0000; constexpr int ORBIS_KERNEL_O_WRONLY = 0x0001; diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index e2f73afe..71abbb58 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -113,12 +113,16 @@ s32 PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool enable) { return SCE_OK; } +int PS4_SYSV_ABI scePadGetHandle(s32 userId, int32_t type, int32_t index) { + return 1; +} + void padSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("hv1luiJrqQM", "libScePad", 1, "libScePad", 1, 1, scePadInit); LIB_FUNCTION("xk0AcarP3V4", "libScePad", 1, "libScePad", 1, 1, scePadOpen); LIB_FUNCTION("YndgXqQVV7c", "libScePad", 1, "libScePad", 1, 1, scePadReadState); LIB_FUNCTION("q1cHNfGycLI", "libScePad", 1, "libScePad", 1, 1, scePadRead); - + LIB_FUNCTION("u1GRHp+oWoY", "libScePad", 1, "libScePad", 1, 1, scePadGetHandle); LIB_FUNCTION("gjP9-KQzoUk", "libScePad", 1, "libScePad", 1, 1, scePadGetControllerInformation); LIB_FUNCTION("clVvL4ZDntw", "libScePad", 1, "libScePad", 1, 1, scePadSetMotionSensorState); }