rpcsx/rpcs3/Emu/Cell/lv2/sys_fs.h

385 lines
9.2 KiB
C
Raw Normal View History

2015-03-12 20:02:02 +01:00
#pragma once
2018-07-27 21:07:34 +02:00
#include "Emu/Memory/vm.h"
2016-06-02 17:16:01 +02:00
#include "Emu/Cell/ErrorCodes.h"
2015-03-12 20:02:02 +01:00
// Open Flags
enum : s32
{
2015-03-13 16:06:27 +01:00
CELL_FS_O_RDONLY = 000000,
CELL_FS_O_WRONLY = 000001,
CELL_FS_O_RDWR = 000002,
2015-03-12 20:02:02 +01:00
CELL_FS_O_ACCMODE = 000003,
2015-03-13 16:06:27 +01:00
CELL_FS_O_CREAT = 000100,
CELL_FS_O_EXCL = 000200,
CELL_FS_O_TRUNC = 001000,
CELL_FS_O_APPEND = 002000,
CELL_FS_O_MSELF = 010000,
CELL_FS_O_UNK = 01000000, // Tests have shown this is independent of other flags. Only known to be called in Rockband games.
2015-03-12 20:02:02 +01:00
};
// Seek Mode
enum : s32
{
CELL_FS_SEEK_SET,
CELL_FS_SEEK_CUR,
CELL_FS_SEEK_END,
};
enum : s32
{
CELL_FS_MAX_FS_PATH_LENGTH = 1024,
CELL_FS_MAX_FS_FILE_NAME_LENGTH = 255,
CELL_FS_MAX_MP_LENGTH = 31,
};
2016-06-02 17:16:01 +02:00
enum : s32
2015-03-12 20:02:02 +01:00
{
2015-03-13 02:09:53 +01:00
CELL_FS_S_IFMT = 0170000,
2015-03-12 20:02:02 +01:00
CELL_FS_S_IFDIR = 0040000, // directory
CELL_FS_S_IFREG = 0100000, // regular
CELL_FS_S_IFLNK = 0120000, // symbolic link
CELL_FS_S_IFWHT = 0160000, // unknown
CELL_FS_S_IRUSR = 0000400, // R for owner
CELL_FS_S_IWUSR = 0000200, // W for owner
CELL_FS_S_IXUSR = 0000100, // X for owner
CELL_FS_S_IRGRP = 0000040, // R for group
CELL_FS_S_IWGRP = 0000020, // W for group
CELL_FS_S_IXGRP = 0000010, // X for group
CELL_FS_S_IROTH = 0000004, // R for other
CELL_FS_S_IWOTH = 0000002, // W for other
CELL_FS_S_IXOTH = 0000001, // X for other
};
// CellFsDirent.d_type
enum : u8
{
2015-03-13 16:06:27 +01:00
CELL_FS_TYPE_UNKNOWN = 0,
2015-03-12 20:02:02 +01:00
CELL_FS_TYPE_DIRECTORY = 1,
2015-03-13 16:06:27 +01:00
CELL_FS_TYPE_REGULAR = 2,
CELL_FS_TYPE_SYMLINK = 3,
2015-03-12 20:02:02 +01:00
};
struct CellFsDirent
{
u8 d_type;
u8 d_namlen;
char d_name[256];
};
struct CellFsStat
{
2015-03-13 02:09:53 +01:00
be_t<s32> mode;
2015-03-12 20:02:02 +01:00
be_t<s32> uid;
be_t<s32> gid;
2016-05-26 17:06:06 +02:00
be_t<s64, 4> atime;
be_t<s64, 4> mtime;
be_t<s64, 4> ctime;
be_t<u64, 4> size;
be_t<u64, 4> blksize;
2015-03-12 20:02:02 +01:00
};
2016-05-26 17:06:06 +02:00
CHECK_SIZE_ALIGN(CellFsStat, 52, 4);
2017-04-22 14:29:20 +02:00
struct CellFsDirectoryEntry
{
CellFsStat attribute;
CellFsDirent entry_name;
};
2015-03-12 20:02:02 +01:00
struct CellFsUtimbuf
{
2016-05-26 17:06:06 +02:00
be_t<s64, 4> actime;
be_t<s64, 4> modtime;
2015-03-12 20:02:02 +01:00
};
2016-05-26 17:06:06 +02:00
CHECK_SIZE_ALIGN(CellFsUtimbuf, 16, 4);
2015-03-12 20:02:02 +01:00
// MSelf file structs
struct FsMselfHeader
{
be_t<u32> m_magic;
be_t<u32> m_format_version;
be_t<u64> m_file_size;
be_t<u32> m_entry_num;
be_t<u32> m_entry_size;
u8 m_reserve[40];
};
struct FsMselfEntry
{
char m_name[32];
be_t<u64> m_offset;
be_t<u64> m_size;
u8 m_reserve[16];
};
2016-06-02 17:16:01 +02:00
struct lv2_fs_mount_point;
2015-03-16 14:15:52 +01:00
2016-06-02 17:16:01 +02:00
struct lv2_fs_object
2015-03-16 14:15:52 +01:00
{
using id_type = lv2_fs_object;
2017-01-25 18:50:30 +01:00
static const u32 id_base = 3;
static const u32 id_step = 1;
static const u32 id_count = 255 - id_base;
2016-04-14 00:23:53 +02:00
2016-06-02 17:16:01 +02:00
// Mount Point
const std::add_pointer_t<lv2_fs_mount_point> mp;
2017-04-24 18:49:53 +02:00
// File Name (max 1055)
const std::array<char, 0x420> name;
lv2_fs_object(lv2_fs_mount_point* mp, const char* filename)
2016-06-02 17:16:01 +02:00
: mp(mp)
2017-04-24 18:49:53 +02:00
, name(get_name(filename))
2016-06-02 17:16:01 +02:00
{
}
static lv2_fs_mount_point* get_mp(const char* filename);
2017-04-24 18:49:53 +02:00
static std::array<char, 0x420> get_name(const char* filename)
{
std::array<char, 0x420> name;
for (auto& c : name)
{
c = *filename++;
if (!c)
{
return name;
}
}
name.back() = 0;
return name;
}
2016-04-14 00:23:53 +02:00
};
struct lv2_file final : lv2_fs_object
{
2016-04-14 00:23:53 +02:00
const fs::file file;
const s32 mode;
const s32 flags;
2017-04-24 22:30:15 +02:00
// Stream lock
atomic_t<u32> lock{0};
2016-06-02 17:16:01 +02:00
lv2_file(const char* filename, fs::file&& file, s32 mode, s32 flags)
2017-04-24 18:49:53 +02:00
: lv2_fs_object(lv2_fs_object::get_mp(filename), filename)
2016-06-02 17:16:01 +02:00
, file(std::move(file))
, mode(mode)
, flags(flags)
{
}
2016-06-02 17:16:01 +02:00
2017-04-24 18:49:53 +02:00
lv2_file(const lv2_file& host, fs::file&& file, s32 mode, s32 flags)
: lv2_fs_object(host.mp, host.name.data())
, file(std::move(file))
, mode(mode)
, flags(flags)
{
}
2016-06-02 17:16:01 +02:00
// File reading with intermediate buffer
2018-02-09 15:49:37 +01:00
u64 op_read(vm::ptr<void> buf, u64 size);
2016-06-02 17:16:01 +02:00
// File writing with intermediate buffer
2018-02-09 15:49:37 +01:00
u64 op_write(vm::cptr<void> buf, u64 size);
// For MSELF support
struct file_view;
// Make file view from lv2_file object (for MSELF support)
static fs::file make_view(const std::shared_ptr<lv2_file>& _file, u64 offset);
};
struct lv2_dir final : lv2_fs_object
2015-07-01 19:09:26 +02:00
{
2016-04-14 00:23:53 +02:00
const fs::dir dir;
2015-07-01 19:09:26 +02:00
2016-06-02 17:16:01 +02:00
lv2_dir(const char* filename, fs::dir&& dir)
2017-04-24 18:49:53 +02:00
: lv2_fs_object(lv2_fs_object::get_mp(filename), filename)
2016-06-02 17:16:01 +02:00
, dir(std::move(dir))
2015-07-01 19:09:26 +02:00
{
}
};
2016-06-02 17:16:01 +02:00
// sys_fs_fcntl arg base class (left empty for PODness)
struct lv2_file_op
{
};
namespace vtable
{
struct lv2_file_op
{
// Speculation
vm::bptrb<vm::ptrb<void>(vm::ptrb<lv2_file_op>)> get_data;
vm::bptrb<u32(vm::ptrb<lv2_file_op>)> get_size;
vm::bptrb<void(vm::ptrb<lv2_file_op>)> _dtor1;
vm::bptrb<void(vm::ptrb<lv2_file_op>)> _dtor2;
};
}
// sys_fs_fcntl: read with offset, write with offset
struct lv2_file_op_rw : lv2_file_op
{
vm::bptrb<vtable::lv2_file_op> _vtable;
be_t<u32> op;
be_t<u32> _x8; // ???
be_t<u32> _xc; // ???
be_t<u32> fd; // File descriptor (3..255)
vm::bptrb<void> buf; // Buffer for data
be_t<u64> offset; // File offset
be_t<u64> size; // Access size
be_t<s32> out_code; // Op result
be_t<u64> out_size; // Size processed
};
CHECK_SIZE(lv2_file_op_rw, 0x38);
// sys_fs_fcntl: cellFsSdataOpenByFd
struct lv2_file_op_09 : lv2_file_op
{
vm::bptrb<vtable::lv2_file_op> _vtable;
be_t<u32> op;
be_t<u32> _x8;
be_t<u32> _xc;
be_t<u32> fd;
be_t<u64> offset;
be_t<u32> _vtabl2;
be_t<u32> arg1; // 0x180
be_t<u32> arg2; // 0x10
be_t<u32> arg_size; // 6th arg
be_t<u32> arg_ptr; // 5th arg
2017-04-23 00:07:41 +02:00
be_t<u32> _x34;
be_t<s32> out_code;
be_t<u32> out_fd;
};
CHECK_SIZE(lv2_file_op_09, 0x40);
2017-04-22 14:29:20 +02:00
// sys_fs_fnctl: cellFsGetDirectoryEntries
struct lv2_file_op_dir : lv2_file_op
{
struct dir_info : lv2_file_op
{
be_t<s32> _code; // Op result
be_t<u32> _size; // Number of entries written
vm::bptrb<CellFsDirectoryEntry> ptr;
be_t<u32> max;
};
CHECK_SIZE(dir_info, 0x10);
vm::bptrb<vtable::lv2_file_op> _vtable;
be_t<u32> op;
be_t<u32> _x8;
dir_info arg;
};
CHECK_SIZE(lv2_file_op_dir, 0x1c);
2017-04-25 02:13:45 +02:00
// sys_fs_fcntl: cellFsGetFreeSize (for dev_hdd0)
struct lv2_file_c0000002 : lv2_file_op
{
vm::bptrb<vtable::lv2_file_op> _vtable;
be_t<u32> op;
be_t<u32> _x8;
2018-02-09 15:49:37 +01:00
vm::bcptr<char> path;
2017-04-25 02:13:45 +02:00
be_t<u32> _x10; // 0
be_t<u32> _x14;
be_t<u32> out_code; // CELL_ENOSYS
be_t<u32> out_block_size;
be_t<u64> out_block_count;
};
CHECK_SIZE(lv2_file_c0000002, 0x28);
// sys_fs_fcntl: unknown (called before cellFsOpen, for example)
2017-04-22 15:01:24 +02:00
struct lv2_file_c0000006 : lv2_file_op
{
be_t<u32> size; // 0x20
be_t<u32> _x4; // 0x10
be_t<u32> _x8; // 0x18
be_t<u32> _xc; // 0x9
2018-02-09 15:49:37 +01:00
vm::bcptr<char> name;
2017-04-22 15:01:24 +02:00
be_t<u32> _x14; // 0
be_t<u32> _x18; // 0x80010003
be_t<u32> _x1c; // 0
};
CHECK_SIZE(lv2_file_c0000006, 0x20);
// sys_fs_fcntl: cellFsAllocateFileAreaWithoutZeroFill
struct lv2_file_e0000017 : lv2_file_op
{
be_t<u32> size; // 0x28
be_t<u32> _x4; // 0x10, offset
be_t<u32> _x8; // 0x20, offset
be_t<u32> _xc; // -
2018-02-09 15:49:37 +01:00
vm::bcptr<char> file_path;
be_t<u64> file_size;
be_t<u32> out_code;
};
CHECK_SIZE(lv2_file_e0000017, 0x28);
2017-02-04 16:09:02 +01:00
// Syscalls
2018-02-09 15:49:37 +01:00
error_code sys_fs_test(u32 arg1, u32 arg2, vm::ptr<u32> arg3, u32 arg4, vm::ptr<char> buf, u32 buf_size);
error_code sys_fs_open(vm::cptr<char> path, s32 flags, vm::ptr<u32> fd, s32 mode, vm::cptr<void> arg, u64 size);
error_code sys_fs_read(u32 fd, vm::ptr<void> buf, u64 nbytes, vm::ptr<u64> nread);
error_code sys_fs_write(u32 fd, vm::cptr<void> buf, u64 nbytes, vm::ptr<u64> nwrite);
error_code sys_fs_close(u32 fd);
2018-02-09 15:49:37 +01:00
error_code sys_fs_opendir(vm::cptr<char> path, vm::ptr<u32> fd);
error_code sys_fs_readdir(u32 fd, vm::ptr<CellFsDirent> dir, vm::ptr<u64> nread);
error_code sys_fs_closedir(u32 fd);
2018-02-09 15:49:37 +01:00
error_code sys_fs_stat(vm::cptr<char> path, vm::ptr<CellFsStat> sb);
error_code sys_fs_fstat(u32 fd, vm::ptr<CellFsStat> sb);
error_code sys_fs_link(vm::cptr<char> from, vm::cptr<char> to);
error_code sys_fs_mkdir(vm::cptr<char> path, s32 mode);
error_code sys_fs_rename(vm::cptr<char> from, vm::cptr<char> to);
error_code sys_fs_rmdir(vm::cptr<char> path);
error_code sys_fs_unlink(vm::cptr<char> path);
error_code sys_fs_access(vm::cptr<char> path, s32 mode);
error_code sys_fs_fcntl(u32 fd, u32 op, vm::ptr<void> arg, u32 size);
error_code sys_fs_lseek(u32 fd, s64 offset, s32 whence, vm::ptr<u64> pos);
error_code sys_fs_fdatasync(u32 fd);
error_code sys_fs_fsync(u32 fd);
2018-02-09 15:49:37 +01:00
error_code sys_fs_fget_block_size(u32 fd, vm::ptr<u64> sector_size, vm::ptr<u64> block_size, vm::ptr<u64> arg4, vm::ptr<s32> arg5);
error_code sys_fs_get_block_size(vm::cptr<char> path, vm::ptr<u64> sector_size, vm::ptr<u64> block_size, vm::ptr<u64> arg4);
error_code sys_fs_truncate(vm::cptr<char> path, u64 size);
error_code sys_fs_ftruncate(u32 fd, u64 size);
2018-02-09 15:49:37 +01:00
error_code sys_fs_symbolic_link(vm::cptr<char> target, vm::cptr<char> linkpath);
error_code sys_fs_chmod(vm::cptr<char> path, s32 mode);
error_code sys_fs_chown(vm::cptr<char> path, s32 uid, s32 gid);
error_code sys_fs_disk_free(vm::cptr<char> path, vm::ptr<u64> total_free, vm::ptr<u64> avail_free);
error_code sys_fs_utime(vm::cptr<char> path, vm::cptr<CellFsUtimbuf> timep);
error_code sys_fs_acl_read(vm::cptr<char> path, vm::ptr<void>);
error_code sys_fs_acl_write(vm::cptr<char> path, vm::ptr<void>);
error_code sys_fs_lsn_get_cda_size(u32 fd, vm::ptr<u64> ptr);
error_code sys_fs_lsn_get_cda(u32 fd, vm::ptr<void>, u64, vm::ptr<u64>);
2017-04-24 22:30:15 +02:00
error_code sys_fs_lsn_lock(u32 fd);
error_code sys_fs_lsn_unlock(u32 fd);
2018-02-09 15:49:37 +01:00
error_code sys_fs_lsn_read(u32 fd, vm::cptr<void>, u64);
error_code sys_fs_lsn_write(u32 fd, vm::cptr<void>, u64);
error_code sys_fs_mapped_allocate(u32 fd, u64, vm::pptr<void> out_ptr);
error_code sys_fs_mapped_free(u32 fd, vm::ptr<void> ptr);
2017-05-10 16:43:04 +02:00
error_code sys_fs_truncate2(u32 fd, u64 size);