Compare commits

...

7 Commits

Author SHA1 Message Date
wheremyfoodat 0a689270b3 fs fixes and clean 2023-10-21 10:31:30 +03:00
georgemoralis 03a95ecadd refactor 2023-10-20 16:13:08 +03:00
georgemoralis 7cfcd952d2 implemented sceKernelClose 2023-10-20 16:11:10 +03:00
georgemoralis 40a3868cbc we can create directories now 2023-10-20 15:39:23 +03:00
georgemoralis 51260ca6ce mount host_folder to guest_folder 2023-10-20 09:09:59 +03:00
georgemoralis 6bd5bfd500 mount points draft 2023-10-20 08:38:54 +03:00
wheremyfoodat fda578a625 initial fs design 2023-10-20 07:51:20 +03:00
12 changed files with 213 additions and 132 deletions

View File

@ -51,6 +51,8 @@ set(FILESYSTEM_SOURCES src/Emulator/HLE/Libraries/LibKernel/FileSystem/file_syst
set(HOST_SOURCES src/Emulator/Host/controller.cpp set(HOST_SOURCES src/Emulator/Host/controller.cpp
src/Emulator/Host/controller.h src/Emulator/Host/controller.h
src/Emulator/Host/fs.cpp
src/Emulator/Host/fs.h
) )
set(UTIL_SOURCES src/Emulator/Util/singleton.h set(UTIL_SOURCES src/Emulator/Util/singleton.h
@ -98,7 +100,7 @@ add_executable(shadps4
src/Core/PS4/HLE/Kernel/cpu_management.cpp src/Core/PS4/HLE/Kernel/cpu_management.cpp
src/Core/PS4/HLE/Kernel/cpu_management.h src/Core/PS4/HLE/Kernel/cpu_management.h
"src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h" "src/Core/PS4/HLE/Graphics/graphics_render.cpp" "src/Core/PS4/HLE/Graphics/graphics_render.h" "src/Core/PS4/GPU/tile_manager.cpp" "src/Core/PS4/GPU/tile_manager.h" "src/version.h" "src/Emulator/HLE/Libraries/LibSystemService/system_service.cpp" "src/Emulator/HLE/Libraries/LibSystemService/system_service.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.h" "src/Emulator/HLE/Libraries/LibKernel/FileSystem/meta_file_system.cpp") "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h" "src/emulator.cpp" "src/emulator.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.h" "src/Core/PS4/HLE/Kernel/Objects/event_queue.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.cpp" "src/Core/PS4/HLE/Graphics/Objects/video_out_ctx.h" "src/Core/PS4/HLE/Graphics/graphics_ctx.h" "src/vulkan_util.cpp" "src/vulkan_util.h" "src/Core/PS4/GPU/video_out_buffer.cpp" "src/Core/PS4/GPU/video_out_buffer.h" "src/Core/PS4/HLE/Graphics/graphics_render.cpp" "src/Core/PS4/HLE/Graphics/graphics_render.h" "src/Core/PS4/GPU/tile_manager.cpp" "src/Core/PS4/GPU/tile_manager.h" "src/version.h")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY} vulkan-1 spirv-tools-opt spirv-tools)

View File

@ -4,7 +4,9 @@ constexpr int SCE_OK = 0;
constexpr int SCE_KERNEL_ERROR_EBADF = 0x80020009; constexpr int SCE_KERNEL_ERROR_EBADF = 0x80020009;
constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c; // Insufficient memory constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c; // Insufficient memory
constexpr int SCE_KERNEL_ERROR_EFAULT = 0x8002000e; // Invalid address pointer constexpr int SCE_KERNEL_ERROR_EFAULT = 0x8002000e; // Invalid address pointer
constexpr int SCE_KERNEL_ERROR_ENOTDIR = 0x80020014;
constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; // null or invalid states constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; // null or invalid states
constexpr int SCE_KERNEL_ERROR_EMFILE = 0x80020018; // Limit on the number of file descriptors that can be open has been reached
constexpr int SCE_KERNEL_ERROR_EAGAIN = 0x80020023; // Memory cannot be allocated constexpr int SCE_KERNEL_ERROR_EAGAIN = 0x80020023; // Memory cannot be allocated
constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003f; // character strings exceeds valid size constexpr int SCE_KERNEL_ERROR_ENAMETOOLONG = 0x8002003f; // character strings exceeds valid size

View File

@ -48,6 +48,7 @@ void LibKernel_Register(SymbolsResolver* sym) {
LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc); LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc);
// fs // fs
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, Emulator::HLE::Libraries::LibKernel::FileSystem::sceKernelOpen); LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, Emulator::HLE::Libraries::LibKernel::FileSystem::sceKernelOpen);
LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, Emulator::HLE::Libraries::LibKernel::FileSystem::sceKernelClose);
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, Emulator::HLE::Libraries::LibKernel::FileSystem::POSIX::open); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, Emulator::HLE::Libraries::LibKernel::FileSystem::POSIX::open);
} }

View File

@ -1,13 +1,55 @@
#include "file_system.h" #include "file_system.h"
#include <debug.h>
#include <Core/PS4/HLE/ErrorCodes.h>
#include <Emulator/Util/singleton.h>
#include <Util/log.h> #include <Util/log.h>
#include <debug.h>
#include "Emulator/Host/fs.h"
namespace Emulator::HLE::Libraries::LibKernel::FileSystem { namespace Emulator::HLE::Libraries::LibKernel::FileSystem {
constexpr bool log_file_fs = true; // disable it to disable logging constexpr bool log_file_fs = true; // disable it to disable logging
int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) { int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {} mode = {}\n", path, log_hex_full(flags), log_hex_full(mode)); LOG_INFO_IF(log_file_fs, "sceKernelOpen path = {} flags = {} mode = {}\n", path, log_hex_full(flags), log_hex_full(mode));
return 0;
bool isDirectory = (flags & SCE_KERNEL_O_DIRECTORY) != 0;
bool create = (flags & SCE_KERNEL_O_CREAT) != 0;
auto* h = singleton<Emulator::Host::Fs::HandleTable>::instance();
auto* mnt = singleton<Emulator::Host::Fs::MntPoints>::instance();
u32 handle = 0;
if (h->createHandle().has_value()) {
handle = h->createHandle().value();
} else {
return SCE_KERNEL_ERROR_EMFILE; // file descriptors is full error(?)
}
Emulator::Host::Fs::File* file = h->getFile(handle);
file->guest_path = path;
if (isDirectory) {
file->host_path = mnt->getHostDirectory(path);
if (!std::filesystem::is_directory(file->host_path)) { // directory doesn't exist
if (create) { // if we have a create flag create it
if (std::filesystem::create_directories(file->host_path)) {
return handle;
} else {
return SCE_KERNEL_ERROR_ENOTDIR;
}
} else {
return SCE_KERNEL_ERROR_ENOTDIR;
}
}
}
return handle;
} }
int PS4_SYSV_ABI sceKernelClose(int handle) {
LOG_INFO_IF(log_file_fs, "sceKernelClose descriptor = {}\n", handle);
auto* h = singleton<Emulator::Host::Fs::HandleTable>::instance();
Emulator::Host::Fs::File* file = h->getFile(handle);
file->valid = false;
h->freeHandle(handle);
return SCE_OK;
}
} // namespace Emulator::HLE::Libraries::LibKernel::FileSystem } // namespace Emulator::HLE::Libraries::LibKernel::FileSystem

View File

@ -2,6 +2,11 @@
#include <types.h> #include <types.h>
namespace Emulator::HLE::Libraries::LibKernel::FileSystem { namespace Emulator::HLE::Libraries::LibKernel::FileSystem {
int PS4_SYSV_ABI sceKernelOpen(const char *path, int flags, /* SceKernelMode*/ u16 mode);
} constexpr u32 SCE_KERNEL_O_CREAT = 0x0200;
constexpr u32 SCE_KERNEL_O_DIRECTORY = 0x00020000;
int PS4_SYSV_ABI sceKernelOpen(const char *path, int flags, /* SceKernelMode*/ u16 mode);
int PS4_SYSV_ABI sceKernelClose(int handle);
} // namespace Emulator::HLE::Libraries::LibKernel::FileSystem

View File

@ -1,27 +0,0 @@
#pragma once
#include <types.h>
#include <string>
namespace Emulator::Host::GenericFS {
enum FileAccess {
FILEACCESS_READ = 0,
FILEACCESS_WRITE = 1,
FILEACCESS_READWRITE = 2
};
class GenericHandleAllocator {
public:
virtual u32 requestHandle() = 0;
virtual void releaseHandle(u32 handle) = 0;
};
class AbstractFileSystem {
public:
virtual bool ownsHandle(u32 handle) = 0;
virtual u32 openFile(std::string filename, FileAccess access) = 0;
virtual void closeFile(u32 handle) = 0;
};
} // namespace Emulator::Host::GenericFS

View File

@ -1,52 +0,0 @@
#include "meta_file_system.h"
namespace Emulator::Host::GenericFS {
void MetaFileSystem::mount(std::string prefix, AbstractFileSystem* system) {
System x;
x.prefix = prefix;
x.system = system;
fileSystems.push_back(x);
}
void MetaFileSystem::unMount(AbstractFileSystem* system) {}
void MetaFileSystem::unMountAll() { fileSystems.clear(); }
AbstractFileSystem* MetaFileSystem::getHandleOwner(u32 handle) {
for (u32 i = 0; i < fileSystems.size(); i++) {
if (fileSystems[i].system->ownsHandle(handle)) return fileSystems[i].system; // got it!
}
return nullptr;
}
bool MetaFileSystem::mapFilePath(std::string inpath, std::string* outpath, AbstractFileSystem** system) {
for (unsigned int i = 0; i < fileSystems.size(); i++) {
int prefLen = fileSystems[i].prefix.size();
if (fileSystems[i].prefix == inpath.substr(0, prefLen))
{
*outpath = inpath.substr(prefLen);
*system = fileSystems[i].system;
return true;
}
}
return false;
}
u32 MetaFileSystem::openFile(std::string filename, FileAccess access) {
AbstractFileSystem* system;
std::string of;
if (mapFilePath(filename, &of, &system)) {
return system->openFile(of, access);
}
return 0;
}
void MetaFileSystem::closeFile(u32 handle) {
AbstractFileSystem* sys = getHandleOwner(handle);
if (sys) sys->closeFile(handle);
}
} // namespace Emulator::Host::GenericFS

View File

@ -1,40 +0,0 @@
#pragma once
#include <types.h>
#include <string>
#include <vector>
#include "generic_file_system.h"
namespace Emulator::Host::GenericFS {
class MetaFileSystem : public GenericHandleAllocator, AbstractFileSystem {
struct System {
std::string prefix;
AbstractFileSystem *system;
};
u32 current;
std::vector<System> fileSystems;
std::string currentDirectory;
std::vector<u32> handler;
public:
MetaFileSystem() : current(0) {}
void mount(std::string prefix, AbstractFileSystem *system);
void unMount(AbstractFileSystem *system);
void unMountAll();
AbstractFileSystem *getHandleOwner(u32 handle);
bool mapFilePath(std::string inpath, std::string *outpath, AbstractFileSystem **system);
u32 requestHandle() {
handler.push_back(current);
current++;
return handler.back();
}
void releaseHandle(u32 handle) { handler.erase(std::remove(handler.begin(), handler.end(), handle), handler.end()); }
bool ownsHandle(u32 handle) { return false; }
u32 openFile(std::string filename, FileAccess access);
void closeFile(u32 handle);
};
} // namespace Emulator::Host::GenericFS

View File

@ -1,11 +1,14 @@
#include "posix_file_system.h" #include "posix_file_system.h"
#include <debug.h> #include <debug.h>
#include <Util/log.h>
#include "file_system.h" #include "file_system.h"
namespace Emulator::HLE::Libraries::LibKernel::FileSystem::POSIX { namespace Emulator::HLE::Libraries::LibKernel::FileSystem::POSIX {
constexpr bool log_file_pfs = true; // disable it to disable logging
int PS4_SYSV_ABI open(const char* path, int flags, /* SceKernelMode*/ u16 mode) { int PS4_SYSV_ABI open(const char* path, int flags, /* SceKernelMode*/ u16 mode) {
LOG_INFO_IF(log_file_pfs, "posix open redirect to sceKernelOpen\n");
int result = sceKernelOpen(path, flags, mode); int result = sceKernelOpen(path, flags, mode);
if (result < 0) { if (result < 0) {
BREAKPOINT(); // posix calls different only for their return values BREAKPOINT(); // posix calls different only for their return values

33
src/Emulator/Host/fs.cpp Normal file
View File

@ -0,0 +1,33 @@
#include "fs.h"
#include <algorithm>
namespace Emulator::Host::Fs {
void MntPoints::mount(const std::string& host_folder, const std::string& guest_folder) {
Lib::LockMutexGuard lock(m_mutex);
MntPair pair;
pair.host_path = host_folder;
pair.guest_path = guest_folder;
m_mnt_pairs.push_back(pair);
}
void MntPoints::unMount(const std::string& path) {}
void MntPoints::unmountAll() {}
std::string MntPoints::getHostDirectory(const std::string& guest_directory) {
Lib::LockMutexGuard 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")) {
std::replace(pair.host_path.begin(), pair.host_path.end(), '\\', '/');
return pair.host_path + guest_directory;
}
}
return "";
}
} // namespace Emulator::Host::Fs

108
src/Emulator/Host/fs.h Normal file
View File

@ -0,0 +1,108 @@
#pragma once
#include <types.h>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <optional>
#include <vector>
#include "Lib/Threads.h"
namespace Emulator::Host::Fs {
class MntPoints {
public:
struct MntPair {
std::string host_path;
std::string guest_path; // e.g /app0/
};
MntPoints() {}
virtual ~MntPoints() {}
void mount(const std::string& host_folder, const std::string& guest_folder);
void unMount(const std::string& path);
void unmountAll();
std::string getHostDirectory(const std::string& guest_directory);
private:
std::vector<MntPair> m_mnt_pairs;
Lib::Mutex m_mutex;
};
struct File {
bool valid = false; // Ôï descriptor åéíáé ïíôùò áíïé÷ôï;
FILE* file; // File handle ôïõ áñ÷åéï
std::filesystem::path host_path; // Path in host FS
std::string guest_path; // Path in PS4 FS
File() : valid(true) {}
};
class HandleTable {
std::vector<File> files;
u32 openFileCount = 0; // Ðïóá descriptors å÷ïõìå áíïé÷ôá;
public:
static constexpr u32 MAX_FILE_DESCRIPTORS = 65536;
HandleTable() {
files.reserve(128); // Êáíïõìå reserve ÷ùñï ãéá ìåñéêá áñ÷åéá ãéá íá áðïöõãïõìå allocations
reset();
}
void reset() {
for (auto& f : files) {
if (f.valid) {
// Êáíïõìå fclose ôï áñ÷åéï êáé ï,ôé áëëï åéíáé íá ãéíåé
}
}
files.clear();
openFileCount = 0;
}
// Åðéóôñåöåé handle ãéá íá äçìéïõñãçóïõìå íåï áñ÷åßï
std::optional<u32> createHandle() {
if (openFileCount >= MAX_FILE_DESCRIPTORS) {
// Äåí ìðïñïõìå íá áíïéîïõìå áëëá descriptors, å÷ïõìå âáñåóåé ôï max
return std::nullopt;
}
// Ìðïñïõìå óéãïõñá íá äçìéïõñãçóïõìå handle, ïðïôå áõîáíïõìå ôï handle count
openFileCount += 1;
// Êïéôáìå áí êáíåíá áðôá files óôï vector åéíáé åëåõèåñï ãéá íá ôï êáíïõìå reuse
for (size_t i = 0; i < files.size(); i++) {
// Âñçêáìå åëåõèåñï áñ÷åéï, åðéóôñåöïõìå ôï index ôïõ
if (!files[i].valid) {
return i;
}
}
// Äåí õðáñ÷åé åëåõèåñï óôï vector áëëá äåí å÷ïõìå åîáíôëçóåé ôï cap, ïðïôå ìåãáëùíïõìå ôï vector
// Êáé åðéóôñåöïõìå ôï index ôïõ êáéíïõñãéïõ
u32 handle = files.size();
files.push_back(File());
return handle;
}
File* getFile(u32 handle) { return &files[handle]; }
void freeHandle(u32 handle) {
if (handle >= files.size()) {
// Óôáíôáñ invalid
printf("POUTSA\n");
return;
}
if (files[handle].valid) {
// Ðáëé êáíïõìå fclose êáé ðéðåò êáé ôï ìáñêáñïõìå ãéá reuse
files[handle].valid = false;
// Ìåéïí åíá áíïé÷ôï áñ÷åéï
openFileCount -= 1;
}
}
};
} // namespace Emulator::Host::Fs

View File

@ -5,7 +5,7 @@
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <stdio.h> #include <stdio.h>
#include <filesystem>
#include "imgui.h" #include "imgui.h"
#include "imgui_impl_opengl3.h" #include "imgui_impl_opengl3.h"
#include "imgui_impl_sdl3.h" #include "imgui_impl_sdl3.h"
@ -35,7 +35,8 @@
#include "Core/PS4/HLE/Libs.h" #include "Core/PS4/HLE/Libs.h"
#include "Core/PS4/Linker.h" #include "Core/PS4/Linker.h"
#include "Lib/Threads.h" #include "Lib/Threads.h"
#include "Emulator/Util\singleton.h" #include "Emulator\Util\singleton.h"
#include "Emulator\Host\fs.h"
#include "discord.h" #include "discord.h"
// Main code // Main code
@ -51,9 +52,12 @@ int main(int argc, char* argv[]) {
Emu::emuInit(width, height); Emu::emuInit(width, height);
HLE::Libs::Graphics::VideoOut::videoOutInit(width, height); HLE::Libs::Graphics::VideoOut::videoOutInit(width, height);
Lib::InitThreads(); Lib::InitThreads();
const char* const path = argv[1]; // argument 1 is the path of self file to boot const char* const path = argv[1]; // argument 1 is the path of self file to boot
auto* mnt = singleton<Emulator::Host::Fs::MntPoints>::instance();
std::filesystem::path p = std::string(path);
mnt->mount(p.parent_path().string(), "/app0");
auto* linker = singleton<Linker>::instance(); auto* linker = singleton<Linker>::instance();
HLE::Libs::Init_HLE_Libs(linker->getHLESymbols()); HLE::Libs::Init_HLE_Libs(linker->getHLESymbols());
auto* module = linker->LoadModule(path); // load main executable auto* module = linker->LoadModule(path); // load main executable