This commit is contained in:
Marek Ledworowski 2025-11-06 23:21:25 +01:00
parent 89b91c6f30
commit 340a6a7cf5
5 changed files with 46 additions and 65 deletions

View File

@ -142,8 +142,8 @@ public:
struct Libraries::Kernel::OrbisKernelStat st{};
int chmod(u16 mode) {
u16* st_mode = &this->st.st_mode;
*st_mode = ((*st_mode) & (~0x1FF)) | (mode & 0x1FF);
u16& st_mode = this->st.st_mode;
st_mode = ((st_mode) & (~0x1FF)) | (mode & 0x1FF);
st.st_birthtim.tv_sec = time(0);
return 0;
}

View File

@ -60,7 +60,7 @@ public:
// s64 pread(void* buf, size_t count, u64 offset) override;
// s64 pwrite(const void* buf, size_t count, u64 offset) override;
s32 ftruncate(s64 length) override {
s32 ftruncate(s64 length) final override {
return -QUASI_EISDIR;
}

View File

@ -1,5 +1,7 @@
// INAA License @marecl 2025
#include <iostream>
#include "common/logging/log.h"
#include "core/file_sys/quasifs/quasi_errno.h"
@ -66,16 +68,25 @@ void _printTree(const inode_ptr& node, const std::string& name, int depth) {
std::tm* t = std::localtime(&st.st_mtim.tv_sec);
std::strftime(timebuf, sizeof(timebuf), "%EY-%m-%d %H:%M", t);
LOG_INFO(Kernel_Fs, "[ls -la] {} {:08} {:03d} {}:{} {:>08} {}\t{}{}\n",
file_mode(st.st_mode), st.st_mode, st.st_nlink, /*st.st_uid*/ 0, /* st.st_gid*/ 0,
st.st_size, timebuf, depEnt, name);
// LOG_INFO(Kernel_Fs, "[ls -la] {} {:08} {:03d} {}:{} {:>08} {}\t{}{}\n",
// file_mode(st.st_mode), st.st_mode, st.st_nlink, /*st.st_uid*/ 0, /* st.st_gid*/
// 0, st.st_size, timebuf, depEnt, name);
std::string line = std::format(
"[ls -la] {} {:08o} {:03d} {}:{} {:>08} {}\t{}{}\n", file_mode(st.st_mode), st.st_mode,
st.st_nlink, /*st.st_uid*/ 0, /* st.st_gid*/ 0, st.st_size, timebuf, depEnt, name);
std::cout << "[FileSystem]" << line;
} else
depth--;
if (node->is_link())
LOG_INFO(Kernel_Fs, "[ls -la]\t\t\t\t\t\t\tsymlinked to ->{}\n",
std::static_pointer_cast<Symlink>(node)->follow().string());
if (node->is_link()) {
// LOG_INFO(Kernel_Fs, "[ls -la]\t\t\t\t\t\t\tsymlinked to ->{}\n",
// std::static_pointer_cast<Symlink>(node)->follow().string());
std::string line = std::format("[ls -la]\t\t\t\t\t\t\t\t[->{}]\n",
std::static_pointer_cast<Symlink>(node)->follow().string());
std::cout << "[FileSystem]" << line;
}
if (node->is_dir()) {
if ("." == name)
return;
@ -84,7 +95,10 @@ void _printTree(const inode_ptr& node, const std::string& name, int depth) {
auto dir = std::dynamic_pointer_cast<Directory>(node);
if (dir->mounted_root) {
LOG_INFO(Kernel_Fs, "[ls -la]\t\t\t\t\t\t\t|--{}{}\n", depEnt, "[MOUNTPOINT]");
// LOG_INFO(Kernel_Fs, "[ls -la]\t\t\t\t\t\t\t|--{}{}\n", depEnt, "[MOUNTPOINT]");
std::string line =
std::format("[ls -la]\t\t\t\t\t\t\t\t|--{}{}\n", depEnt, "[MOUNTPOINT]");
std::cout << "[FileSystem]" << line;
_printTree(dir->mounted_root, "", depth + 1);
} else {
for (auto& childName : dir->Entries()) {

View File

@ -8,14 +8,13 @@
namespace QuasiFS {
s64 VirtualFile::pread(void* buf, size_t count, s64 offset) {
s64 idx;
s64 read_amt = this->data.size() - offset - count;
// if >= 0 - we're good to go
// <0 - n-bytes are missing, won't enter loop
read_amt = count + read_amt * (read_amt < 0);
for (idx = 0; idx < read_amt; idx++) {
for (s64 idx = 0; idx < read_amt; idx++) {
char c = this->data.at(idx + offset);
static_cast<char*>(buf)[idx] = c;
}
@ -25,14 +24,14 @@ s64 VirtualFile::pread(void* buf, size_t count, s64 offset) {
}
s64 VirtualFile::pwrite(const void* buf, size_t count, s64 offset) {
auto size = &this->st.st_size;
auto& size = this->st.st_size;
auto end_pos = offset + count;
*size = end_pos > *size ? end_pos : *size;
size = end_pos > size ? end_pos : size;
// size can only be greater, so it will always scale up
this->data.resize(*size, 0);
this->data.resize(size, 0);
for (u64 idx = offset; idx < *size; idx++)
for (u64 idx = offset; idx < size; idx++)
this->data[idx] = static_cast<const char*>(buf)[idx];
st.st_mtim.tv_sec = time(0);

View File

@ -101,29 +101,24 @@ void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
qfs::partition_ptr partition_dev = qfs::Partition::Create("", 0755, 16384, 16384);
qfs->Operation.MKDir("/app0", 0555);
qfs->Operation.MKDir("/hostapp", 0555);
qfs->Operation.MKDir("/av_contents", 0775);
qfs->Operation.MKDir("/av_contents/photo", 0755);
qfs->Operation.MKDir("/av_contents/thumbnails", 0755);
qfs->Operation.MKDir("/av_contents/video", 0755);
qfs->Operation.MKDir("/data", 0777);
qfs->Operation.MKDir("/dev", 0555);
qfs->Operation.MKDir("/download0", 0777); // not sure about perms here
qfs->Operation.MKDir("/host", 0777);
qfs->Operation.MKDir("/hostapp", 0777);
qfs->Operation.MKDir("/temp", 0777);
qfs->Operation.MKDir("/temp0", 0777);
qfs->Mount("/app0", partition_app0, qfs::MountOptions::MOUNT_NOOPT);
qfs->Mount("/av_contents", partition_av_contents, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/dev", partition_dev, qfs::MountOptions::MOUNT_RW);
// mounting av_contents would shadow these
qfs->Operation.MKDir("/av_contents/photo", 0755);
qfs->Operation.MKDir("/av_contents/thumbnails", 0755);
qfs->Operation.MKDir("/av_contents/video", 0755);
qfs->Mount("/av_contents/photo", partition_av_contents_photo, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/av_contents/thumbnails", partition_av_contents_thumbs,
qfs::MountOptions::MOUNT_RW);
qfs->Mount("/av_contents/video", partition_av_contents_video, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/dev", partition_dev, qfs::MountOptions::MOUNT_RW);
qfs->Mount("/hostapp", partition_app0,
qfs::MountOptions::MOUNT_NOOPT | qfs::MountOptions::MOUNT_BIND);
//
// Setup /dev
//
@ -156,11 +151,11 @@ void Emulator::LoadFilesystem(const std::filesystem::path& game_folder) {
qfs->Operation.Chmod("/dev/srandom", 0666);
if (int fd_dev = qfs->Operation.Open("/dev/stdin", QUASI_O_RDONLY); fd_dev != 0)
LOG_CRITICAL(Kernel_Fs, "XDXDXD 0");
LOG_CRITICAL(Kernel_Fs, "file descriptor of stdin is not 0 (it's {})", fd_dev);
if (int fd_dev = qfs->Operation.Open("/dev/stdout", QUASI_O_WRONLY); fd_dev != 1)
LOG_CRITICAL(Kernel_Fs, "XDXDXD 1 != {}", fd_dev);
LOG_CRITICAL(Kernel_Fs, "file descriptor of stdout is not 1 (it's {})", fd_dev);
if (int fd_dev = qfs->Operation.Open("/dev/stderr", QUASI_O_WRONLY); fd_dev != 2)
LOG_CRITICAL(Kernel_Fs, "XDXDXD 2 != {}", fd_dev);
LOG_CRITICAL(Kernel_Fs, "file descriptor of stderr is not 2 (it's {})", fd_dev);
qfs->SyncHost();
@ -201,8 +196,6 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
// Applications expect to be run from /app0 so mount the file's parent path as app0.
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
mnt->Mount(game_folder, "/app0", true);
// Certain games may use /hostapp as well such as CUSA001100
mnt->Mount(game_folder, "/hostapp", true);
this->LoadFilesystem(game_folder);
@ -267,6 +260,10 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
}
std::filesystem::create_directory(mount_temp_dir);
qfs->Operation.MKDir("/data", 0777);
qfs->Operation.MKDir("/download0", 0777); // not sure about perms here
qfs->Operation.MKDir("/temp", 0777);
qfs->Operation.MKDir("/temp0", 0777);
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);
@ -420,42 +417,13 @@ 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;
// 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;
// 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);
// 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;
// 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);
// if (!std::filesystem::exists(mount_captures_dir)) {
// std::filesystem::create_directory(mount_captures_dir);
// }
// VideoCore::SetOutputDir(mount_captures_dir, id);
// Initialize kernel and library facilities.
Libraries::InitHLELibs(&linker->GetHLESymbols());
// Load the module with the linker
auto guest_eboot_path = "/app0/" + eboot_name.generic_string();
const auto eboot_path = mnt->GetHostPath(guest_eboot_path);
std::filesystem::path eboot_path{};
qfs->GetHostPath(eboot_path, guest_eboot_path);
if (linker->LoadModule(eboot_path) == -1) {
LOG_CRITICAL(Loader, "Failed to load game's eboot.bin: {}",
Common::FS::PathToUTF8String(std::filesystem::absolute(eboot_path)));