mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-29 07:14:20 -06:00
Windows shenanigans
Modified FS init flow Added mk/rmdir, fixed close() Added (p)read/write Fixed path being treated as relative on windows Fixed incorrect resolution of mountpoint roots (requires validation)
This commit is contained in:
parent
1c8f24945a
commit
6b338d860a
@ -91,14 +91,14 @@ public:
|
||||
s32 Truncate(const fs::path& path, u64 size) override;
|
||||
s32 FTruncate(const s32 fd, u64 size) override;
|
||||
|
||||
// s64 Write(const s32 fd, const void* buf, u64 count) override;
|
||||
// s64 Read(const s32 fd, void* buf, u64 count) override;
|
||||
s64 Write(const s32 fd, const void* buf, u64 count) override;
|
||||
s64 Read(const s32 fd, void* buf, u64 count) override;
|
||||
|
||||
// s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
|
||||
// s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
|
||||
s64 PWrite(const s32 fd, const void* buf, u64 count, u64 offset) override;
|
||||
s64 PRead(const s32 fd, void* buf, u64 count, u64 offset) override;
|
||||
|
||||
// s32 MKDir(const fs::path& path, u16 mode = 0755) override;
|
||||
// s32 RMDir(const fs::path& path) override;
|
||||
s32 MKDir(const fs::path& path, u16 mode = 0755) override;
|
||||
s32 RMDir(const fs::path& path) override;
|
||||
|
||||
// s32 Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) override;
|
||||
// s32 FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) override;
|
||||
|
||||
@ -25,6 +25,8 @@ s32 HostIO_Win32::Creat(const fs::path& path, u16 mode) {
|
||||
|
||||
s32 HostIO_Win32::Close(const s32 fd) {
|
||||
errno = 0;
|
||||
if (fd < 0)
|
||||
return -EBADF;
|
||||
s32 status = _close(fd);
|
||||
return 0 == status ? 0 : -errno;
|
||||
}
|
||||
@ -84,4 +86,60 @@ int HostIO_Win32::FTruncate(const s32 fd, u64 size) {
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::Write(const s32 fd, const void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = _write(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::Read(const s32 fd, void* buf, u64 count) {
|
||||
errno = 0;
|
||||
s32 status = _read(fd, buf, count);
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::PWrite(const s32 fd, const void* buf, u64 count, u64 offset) {
|
||||
errno = 0;
|
||||
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
|
||||
if (bak < 0)
|
||||
return -errno;
|
||||
LSeek(fd, offset, SeekOrigin::ORIGIN);
|
||||
|
||||
s32 status = _write(fd, buf, count);
|
||||
|
||||
LSeek(fd, bak, SeekOrigin::ORIGIN);
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s64 HostIO_Win32::PRead(const s32 fd, void* buf, u64 count, u64 offset) {
|
||||
errno = 0;
|
||||
s64 bak = LSeek(fd, 0, SeekOrigin::CURRENT);
|
||||
if (bak < 0)
|
||||
return -errno;
|
||||
LSeek(fd, offset, SeekOrigin::ORIGIN);
|
||||
|
||||
s32 status = _read(fd, buf, count);
|
||||
|
||||
LSeek(fd, bak, SeekOrigin::ORIGIN);
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::MKDir(const fs::path& path, u16 mode) {
|
||||
errno = 0;
|
||||
s32 status = _wmkdir(path.c_str());
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
s32 HostIO_Win32::RMDir(const fs::path& path) {
|
||||
errno = 0;
|
||||
s32 status = _wrmdir(path.c_str());
|
||||
return status >= 0 ? status : -errno;
|
||||
}
|
||||
|
||||
// s32 HostIO_Win32::Stat(const fs::path& path, Libraries::Kernel::OrbisKernelStat* statbuf) {}
|
||||
// s32 HostIO_Win32::FStat(const s32 fd, Libraries::Kernel::OrbisKernelStat* statbuf) {}
|
||||
|
||||
// s32 HostIO_Win32::Chmod(const fs::path& path, u16 mode) {}
|
||||
// s32 HostIO_Win32::FChmod(const s32 fd, u16 mode) {}
|
||||
|
||||
} // namespace HostIODriver
|
||||
@ -228,10 +228,10 @@ int QFS::ForceInsert(const fs::path& path, const std::string& name, inode_ptr no
|
||||
// DO NOT, AND I SWEAR D O N O T touch this function
|
||||
// Debugging it is a royal PITA
|
||||
int QFS::Resolve(const fs::path& path, Resolved& res) {
|
||||
if (path.empty())
|
||||
return -QUASI_EINVAL;
|
||||
if (path.is_relative())
|
||||
if (path.empty() || !path.string().starts_with("/"))
|
||||
return -QUASI_EINVAL;
|
||||
// if (path.is_relative())
|
||||
// return -QUASI_EINVAL;
|
||||
|
||||
// on return:
|
||||
// node - last element of the path (if exists)
|
||||
@ -303,6 +303,7 @@ int QFS::Resolve(const fs::path& path, Resolved& res) {
|
||||
res.mountpoint = mounted_partition;
|
||||
res.parent = mntparent;
|
||||
res.node = mntroot;
|
||||
res.local_path = "/";
|
||||
res.leaf = "/";
|
||||
|
||||
if (iter_path != "/")
|
||||
|
||||
@ -84,11 +84,11 @@ inode_ptr Partition::GetInodeByFileno(fileno_t fileno) {
|
||||
// DO NOT, AND I SWEAR D O N O T touch this function
|
||||
// Debugging it is a royal PITA
|
||||
int Partition::Resolve(fs::path& path, Resolved& res) {
|
||||
if (path.empty())
|
||||
if (path.empty() || !path.string().starts_with("/"))
|
||||
return -QUASI_EINVAL;
|
||||
|
||||
if (path.is_relative())
|
||||
return -QUASI_EBADF;
|
||||
// if (path.is_relative())
|
||||
// return -QUASI_EBADF;
|
||||
|
||||
if (path.string().size() >= 256)
|
||||
return -QUASI_ENAMETOOLONG;
|
||||
|
||||
@ -72,15 +72,20 @@ s32 QFS::OperationImpl::Open(const fs::path& path, int flags, u16 mode) {
|
||||
int vio_status = 0;
|
||||
|
||||
if (part->IsHostMounted()) {
|
||||
fs::path host_path_target{};
|
||||
if (int hostpath_status = part->GetHostPath(host_path_target, res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
|
||||
if (hio_status = qfs.hio_driver.Open(host_path_target, flags, mode); hio_status < 0)
|
||||
// hosts operation must succeed in order to continue
|
||||
return hio_status;
|
||||
host_used = true;
|
||||
if (nullptr == res.node || (res.node && !res.node->is_dir())) {
|
||||
// if doesn't exist, creation/throwing becomes host's problem
|
||||
// however we might want to open a dir for dirents, which would be suboptimal
|
||||
fs::path host_path_target{};
|
||||
if (int hostpath_status = part->GetHostPath(host_path_target, res.local_path);
|
||||
hostpath_status != 0)
|
||||
return hostpath_status;
|
||||
|
||||
if (hio_status = qfs.hio_driver.Open(host_path_target, flags, mode); hio_status < 0)
|
||||
// hosts operation must succeed in order to continue
|
||||
return hio_status;
|
||||
host_used = true;
|
||||
}
|
||||
}
|
||||
|
||||
qfs.vio_driver.SetCtx(&res, host_used, nullptr);
|
||||
|
||||
@ -552,7 +552,7 @@ static s64 GetDents(s32 fd, char* buf, u64 nbytes, s64* basep) {
|
||||
|
||||
s32 result = f->node->getdents(buf, nbytes, basep);
|
||||
if (result < 0) {
|
||||
ErrSceToPosix(result);
|
||||
*__Error() = -result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
106
src/emulator.cpp
106
src/emulator.cpp
@ -88,38 +88,23 @@ Emulator::Emulator() {
|
||||
|
||||
Emulator::~Emulator() {}
|
||||
|
||||
void Emulator::LoadFilesystem(const std::string& id) {
|
||||
const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
||||
if (!std::filesystem::exists(mount_data_dir)) {
|
||||
std::filesystem::create_directory(mount_data_dir);
|
||||
}
|
||||
const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
|
||||
if (std::filesystem::exists(mount_temp_dir)) {
|
||||
// Temp folder should be cleared on each boot.
|
||||
std::filesystem::remove_all(mount_temp_dir);
|
||||
}
|
||||
std::filesystem::create_directory(mount_temp_dir);
|
||||
const auto& mount_download_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
|
||||
if (!std::filesystem::exists(mount_download_dir)) {
|
||||
std::filesystem::create_directory(mount_download_dir);
|
||||
}
|
||||
|
||||
void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
|
||||
auto* qfs = Common::Singleton<qfs::QFS>::Instance();
|
||||
|
||||
qfs->Operation.MKDir("/app0", 0555);
|
||||
qfs->Operation.MKDir("/hostapp", 0555);
|
||||
qfs::partition_ptr partition_app0 = qfs::Partition::Create(game_folder, 0555, 512, 65536);
|
||||
|
||||
qfs->Mount("/app0", partition_app0, qfs::MountOptions::MOUNT_NOOPT);
|
||||
qfs->Mount("/hostapp", partition_app0,
|
||||
qfs::MountOptions::MOUNT_NOOPT | qfs::MountOptions::MOUNT_BIND);
|
||||
|
||||
qfs->Operation.Chmod("/", 0777);
|
||||
qfs::partition_ptr partition_av_contents = qfs::Partition::Create("", 0775, 512, 16384);
|
||||
qfs::partition_ptr partition_av_contents_photo = qfs::Partition::Create("", 0755, 4096, 32768);
|
||||
qfs::partition_ptr partition_av_contents_thumbs = qfs::Partition::Create("", 0755, 4096, 32768);
|
||||
qfs::partition_ptr partition_av_contents_video = qfs::Partition::Create("", 0755, 4096, 32768);
|
||||
|
||||
qfs::partition_ptr partition_data = qfs::Partition::Create(mount_data_dir, 0777, 4096, 32768);
|
||||
qfs::partition_ptr partition_dev = qfs::Partition::Create("", 0755, 16384, 16384);
|
||||
// no idea what are the block sizes for these 3
|
||||
qfs::partition_ptr partition_download =
|
||||
qfs::Partition::Create(mount_download_dir, 0777, 512, 65536);
|
||||
|
||||
qfs::partition_ptr partition_temp = qfs::Partition::Create(mount_temp_dir, 0777, 512, 16384);
|
||||
|
||||
qfs->Operation.MKDir("/av_contents", 0775);
|
||||
qfs->Operation.MKDir("/av_contents/photo", 0755);
|
||||
@ -138,13 +123,7 @@ void Emulator::LoadFilesystem(const std::string& id) {
|
||||
qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/av_contents/video", partition_av_contents_video, qfs::MountOptions::MOUNT_RW);
|
||||
|
||||
qfs->Mount("/data", partition_data, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/dev", partition_dev, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/download0", partition_download, qfs::MountOptions::MOUNT_RW);
|
||||
|
||||
qfs->Mount("/temp", partition_temp, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/temp0", partition_temp,
|
||||
qfs::MountOptions::MOUNT_RW | qfs::MountOptions::MOUNT_BIND);
|
||||
|
||||
//
|
||||
// Setup /dev
|
||||
@ -184,17 +163,11 @@ void Emulator::LoadFilesystem(const std::string& id) {
|
||||
if (int fd_dev = qfs->Operation.Open("/dev/stderr", QUASI_O_WRONLY); fd_dev != 2)
|
||||
LOG_CRITICAL(Kernel_Fs, "XDXDXD 2 != {}", fd_dev);
|
||||
|
||||
//
|
||||
|
||||
const auto& mount_captures_dir = Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
|
||||
if (!std::filesystem::exists(mount_captures_dir)) {
|
||||
std::filesystem::create_directory(mount_captures_dir);
|
||||
}
|
||||
VideoCore::SetOutputDir(mount_captures_dir, id);
|
||||
|
||||
qfs->SyncHost();
|
||||
|
||||
// qfs::printTree(qfs->GetRoot(), "/");
|
||||
qfs::printTree(qfs->GetRoot(), "/");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
@ -232,15 +205,10 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
// Certain games may use /hostapp as well such as CUSA001100
|
||||
mnt->Mount(game_folder, "/hostapp", true);
|
||||
|
||||
auto* qfs = Common::Singleton<qfs::QFS>::Instance();
|
||||
qfs->Operation.MKDir("/app0", 0555);
|
||||
qfs::partition_ptr partition_app0 = qfs::Partition::Create(game_folder, 0555, 512, 65536);
|
||||
|
||||
qfs->Mount("/app0", partition_app0, qfs::MountOptions::MOUNT_NOOPT);
|
||||
qfs->Mount("/hostapp", partition_app0,
|
||||
qfs::MountOptions::MOUNT_NOOPT | qfs::MountOptions::MOUNT_BIND);
|
||||
this->LoadFilesystem(game_folder);
|
||||
|
||||
// can't sync here, otherwise all mountpoints would need to be updated one by one
|
||||
auto* qfs = Common::Singleton<qfs::QFS>::Instance();
|
||||
std::filesystem::path param_sfo_path{};
|
||||
{
|
||||
qfs::Resolved res{};
|
||||
@ -278,7 +246,41 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
psf_attributes.raw = *raw_attributes;
|
||||
}
|
||||
|
||||
this->LoadFilesystem(id);
|
||||
const auto& mount_captures_dir = Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
|
||||
if (!std::filesystem::exists(mount_captures_dir)) {
|
||||
std::filesystem::create_directory(mount_captures_dir);
|
||||
}
|
||||
VideoCore::SetOutputDir(mount_captures_dir, id);
|
||||
|
||||
const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
||||
if (!std::filesystem::exists(mount_data_dir)) {
|
||||
std::filesystem::create_directory(mount_data_dir);
|
||||
}
|
||||
const auto& mount_download_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
|
||||
if (!std::filesystem::exists(mount_download_dir)) {
|
||||
std::filesystem::create_directory(mount_download_dir);
|
||||
}
|
||||
const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
|
||||
if (std::filesystem::exists(mount_temp_dir)) {
|
||||
// Temp folder should be cleared on each boot.
|
||||
std::filesystem::remove_all(mount_temp_dir);
|
||||
}
|
||||
std::filesystem::create_directory(mount_temp_dir);
|
||||
|
||||
qfs::partition_ptr partition_data = qfs::Partition::Create(mount_data_dir, 0777, 4096, 32768);
|
||||
qfs::partition_ptr partition_download =
|
||||
qfs::Partition::Create(mount_download_dir, 0777, 512, 65536);
|
||||
qfs::partition_ptr partition_temp = qfs::Partition::Create(mount_temp_dir, 0777, 512, 16384);
|
||||
qfs->Mount("/data", partition_data, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/download0", partition_download, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/temp", partition_temp, qfs::MountOptions::MOUNT_RW);
|
||||
qfs->Mount("/temp0", partition_temp,
|
||||
qfs::MountOptions::MOUNT_RW | qfs::MountOptions::MOUNT_BIND);
|
||||
qfs->SyncHost("/data");
|
||||
qfs->SyncHost("/donwload0");
|
||||
qfs->SyncHost("/temp");
|
||||
qfs->SyncHost("/temp0");
|
||||
|
||||
Config::load(Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) / (id + ".toml"),
|
||||
true);
|
||||
@ -419,14 +421,14 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
|
||||
g_window = window.get();
|
||||
|
||||
const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
||||
// const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
||||
if (!std::filesystem::exists(mount_data_dir)) {
|
||||
std::filesystem::create_directory(mount_data_dir);
|
||||
}
|
||||
mnt->Mount(mount_data_dir, "/data"); // should just exist, manually create with game serial
|
||||
|
||||
// Mounting temp folders
|
||||
const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
|
||||
//const auto& mount_temp_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
|
||||
if (std::filesystem::exists(mount_temp_dir)) {
|
||||
// Temp folder should be cleared on each boot.
|
||||
std::filesystem::remove_all(mount_temp_dir);
|
||||
@ -435,14 +437,14 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
|
||||
mnt->Mount(mount_temp_dir, "/temp0");
|
||||
mnt->Mount(mount_temp_dir, "/temp");
|
||||
|
||||
const auto& mount_download_dir =
|
||||
Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
|
||||
// const auto& mount_download_dir =
|
||||
// Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
|
||||
if (!std::filesystem::exists(mount_download_dir)) {
|
||||
std::filesystem::create_directory(mount_download_dir);
|
||||
}
|
||||
mnt->Mount(mount_download_dir, "/download0");
|
||||
|
||||
const auto& mount_captures_dir = Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
|
||||
// const auto& mount_captures_dir = Common::FS::GetUserPath(Common::FS::PathType::CapturesDir);
|
||||
if (!std::filesystem::exists(mount_captures_dir)) {
|
||||
std::filesystem::create_directory(mount_captures_dir);
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public:
|
||||
|
||||
private:
|
||||
void LoadSystemModules(const std::string& game_serial);
|
||||
void LoadFilesystem(const std::string& id);
|
||||
void LoadFilesystem(const std::filesystem::path& game_folder);
|
||||
|
||||
Core::MemoryManager* memory;
|
||||
Input::GameController* controller;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user