mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-25 12:15:32 -06:00
fread, _Frprep
Also changed some parameter names a tad to match how I named things in my decomp. And fixed some bugs with how I was handling the weird offseted mode thing
This commit is contained in:
parent
2d93486bff
commit
cb6a0ecd7d
@ -5,6 +5,7 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <common/va_ctx.h>
|
||||
#include "common/alignment.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
@ -193,14 +194,14 @@ s32 PS4_SYSV_ABI internal__Fopen(const char* path, u16 mode, bool flag) {
|
||||
}
|
||||
|
||||
OrbisFILE* PS4_SYSV_ABI internal_fopen(const char* path, const char* mode) {
|
||||
std::scoped_lock lk{g_stream_mtx};
|
||||
std::scoped_lock lk{g_file_mtx};
|
||||
OrbisFILE* file = internal__Fofind();
|
||||
return internal__Foprep(path, mode, file, -1, 0, 0);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* stream) {
|
||||
if (stream == nullptr) {
|
||||
std::scoped_lock lk{g_stream_mtx};
|
||||
s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* file) {
|
||||
if (file == nullptr) {
|
||||
std::scoped_lock lk{g_file_mtx};
|
||||
s32 fflush_result = 0;
|
||||
for (OrbisFILE* file : g_files) {
|
||||
s32 res = internal_fflush(file);
|
||||
@ -210,32 +211,33 @@ s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* stream) {
|
||||
}
|
||||
return fflush_result;
|
||||
}
|
||||
if ((stream->_Mode & 0x2000) != 0) {
|
||||
internal__Lockfilelock(stream);
|
||||
u16 file_mode = stream->_Mode;
|
||||
u8* file_buf_start = stream->_Buf;
|
||||
u8* file_buf_end = stream->_Next;
|
||||
if ((file->_Mode & 0x2000) != 0) {
|
||||
internal__Lockfilelock(file);
|
||||
u16 file_mode = file->_Mode;
|
||||
u8* file_buf_start = file->_Buf;
|
||||
u8* file_buf_end = file->_Next;
|
||||
while (file_buf_start < file_buf_end) {
|
||||
u64 size_to_write = static_cast<u64>(file_buf_end - file_buf_start);
|
||||
s32 write_bytes =
|
||||
Libraries::Kernel::sceKernelWrite(stream->_Handle, file_buf_start, size_to_write);
|
||||
Libraries::Kernel::sceKernelWrite(file->_Handle, file_buf_start, size_to_write);
|
||||
if (write_bytes < 1) {
|
||||
file_buf_start = stream->_Buf;
|
||||
stream->_Next = file_buf_start;
|
||||
stream->_Wend = file_buf_start;
|
||||
stream->_WWend = file_buf_start;
|
||||
stream->_Mode = (stream->_Mode + 1) | 2;
|
||||
internal__Unlockfilelock(stream);
|
||||
file_buf_start = file->_Buf;
|
||||
file->_Next = file_buf_start;
|
||||
file->_Wend = file_buf_start;
|
||||
file->_WWend = file_buf_start;
|
||||
u8* off_mode = reinterpret_cast<u8*>(&file->_Mode) + 1;
|
||||
*off_mode = *off_mode | 2;
|
||||
internal__Unlockfilelock(file);
|
||||
return -1;
|
||||
}
|
||||
file_buf_end = stream->_Next;
|
||||
file_buf_end = file->_Next;
|
||||
file_buf_start += write_bytes;
|
||||
}
|
||||
stream->_Next = file_buf_start;
|
||||
stream->_Wend = file_buf_start;
|
||||
stream->_WWend = file_buf_start;
|
||||
stream->_Mode = file_mode & 0xdfff;
|
||||
internal__Unlockfilelock(stream);
|
||||
file->_Next = file_buf_start;
|
||||
file->_Wend = file_buf_start;
|
||||
file->_WWend = file_buf_start;
|
||||
file->_Mode = file_mode & 0xdfff;
|
||||
internal__Unlockfilelock(file);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -298,18 +300,117 @@ s32 PS4_SYSV_ABI internal__Fspos(OrbisFILE* file, Orbisfpos_t* file_pos, s64 off
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI internal_fseek(OrbisFILE* stream, s64 offset, s32 whence) {
|
||||
internal__Lockfilelock(stream);
|
||||
s32 result = internal__Fspos(stream, nullptr, offset, whence);
|
||||
internal__Unlockfilelock(stream);
|
||||
s32 PS4_SYSV_ABI internal_fseek(OrbisFILE* file, s64 offset, s32 whence) {
|
||||
internal__Lockfilelock(file);
|
||||
s32 result = internal__Fspos(file, nullptr, offset, whence);
|
||||
internal__Unlockfilelock(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 PS4_SYSV_ABI internal_fread(void* ptr, u64 size, u64 nmemb, OrbisFILE* stream) {
|
||||
s32 PS4_SYSV_ABI internal__Frprep(OrbisFILE* file) {
|
||||
if (file->_Rend > file->_Next) {
|
||||
return 1;
|
||||
}
|
||||
if ((file->_Mode & 0x100) == 0) {
|
||||
return 0;
|
||||
}
|
||||
u16 mode = file->_Mode;
|
||||
if ((mode & 0xa001) != 1) {
|
||||
// Lot of magic here, might be valuable to figure out what this does.
|
||||
file->_Mode = (((mode ^ 0x8000) >> 0xf) << 0xe) | mode | 0x200;
|
||||
return -1;
|
||||
}
|
||||
|
||||
u8* file_buf = file->_Buf;
|
||||
if ((mode & 0x800) == 0 && file_buf == &file->_Cbuf) {
|
||||
// Allocate a new file buffer, for now, we'll use host malloc to create it.
|
||||
// When we have an HLE for malloc, that should be used instead.
|
||||
u8* new_buffer = std::bit_cast<u8*>(std::malloc(0x10000));
|
||||
if (new_buffer == nullptr) {
|
||||
file->_Buf = file_buf;
|
||||
file->_Bend = file_buf + 1;
|
||||
} else {
|
||||
file->_Mode = file->_Mode | 0x40;
|
||||
file->_Buf = new_buffer;
|
||||
file->_Bend = new_buffer + 0x10000;
|
||||
file->_WRend = new_buffer;
|
||||
file->_WWend = new_buffer;
|
||||
file_buf = new_buffer;
|
||||
}
|
||||
}
|
||||
file->_Next = file_buf;
|
||||
file->_Rend = file_buf;
|
||||
file->_Wend = file_buf;
|
||||
// Intentional shrinking here, library treats value as 32-bit.
|
||||
s32 read_result =
|
||||
Libraries::Kernel::sceKernelRead(file->_Handle, file_buf, file->_Bend - file_buf);
|
||||
if (read_result < 0) {
|
||||
u8* off_mode = reinterpret_cast<u8*>(&file->_Mode) + 1;
|
||||
*off_mode = *off_mode | 0x42;
|
||||
return -1;
|
||||
} else if (read_result != 0) {
|
||||
file->_Mode = file->_Mode | 0x5000;
|
||||
file->_Rend = file->_Rend + read_result;
|
||||
return 1;
|
||||
}
|
||||
file->_Mode = (file->_Mode & 0xaeff) | 0x4100;
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* stream) {
|
||||
u64 PS4_SYSV_ABI internal_fread(char* ptr, u64 size, u64 nmemb, OrbisFILE* file) {
|
||||
if (size == 0 || nmemb == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (!Common::IsAligned(size * nmemb, 8)) {
|
||||
*Libraries::Kernel::__Error() = POSIX_EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal__Lockfilelock(file);
|
||||
s64 total_size = size * nmemb;
|
||||
s64 remaining_size = total_size;
|
||||
if ((file->_Mode & 0x4000) != 0) {
|
||||
while (remaining_size != 0) {
|
||||
u8* rback_ptr = file->_Rback;
|
||||
if (&file->_Cbuf <= rback_ptr) {
|
||||
break;
|
||||
}
|
||||
file->_Rback = rback_ptr + 1;
|
||||
*ptr = *rback_ptr;
|
||||
ptr++;
|
||||
remaining_size--;
|
||||
}
|
||||
}
|
||||
|
||||
while (remaining_size != 0) {
|
||||
u8* file_ptr = file->_Rsave;
|
||||
if (file_ptr == nullptr) {
|
||||
file_ptr = file->_Rend;
|
||||
} else {
|
||||
file->_Rend = file_ptr;
|
||||
file->_Rsave = nullptr;
|
||||
}
|
||||
u8* src = file->_Next;
|
||||
if (file_ptr <= src) {
|
||||
s32 res = internal__Frprep(file);
|
||||
if (res < 1) {
|
||||
internal__Unlockfilelock(file);
|
||||
return (total_size - remaining_size) / size;
|
||||
}
|
||||
src = file->_Next;
|
||||
file_ptr = file->_Rend;
|
||||
}
|
||||
u64 copy_bytes = std::min<u64>(file_ptr - src, remaining_size);
|
||||
std::memcpy(ptr, src, copy_bytes);
|
||||
file->_Next += copy_bytes;
|
||||
ptr += copy_bytes;
|
||||
remaining_size -= copy_bytes;
|
||||
}
|
||||
internal__Unlockfilelock(file);
|
||||
return (total_size - remaining_size) / size;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -321,6 +422,7 @@ void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("sQL8D-jio7U", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Fopen);
|
||||
LIB_FUNCTION("A+Y3xfrWLLo", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Fspos);
|
||||
LIB_FUNCTION("Ss3108pBuZY", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Nnl);
|
||||
LIB_FUNCTION("9s3P+LCvWP8", "libSceLibcInternal", 1, "libSceLibcInternal", internal__Frprep);
|
||||
LIB_FUNCTION("vZkmJmvqueY", "libSceLibcInternal", 1, "libSceLibcInternal",
|
||||
internal__Lockfilelock);
|
||||
LIB_FUNCTION("0x7rx8TKy2Y", "libSceLibcInternal", 1, "libSceLibcInternal",
|
||||
|
||||
@ -13,7 +13,7 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::LibcInternal {
|
||||
|
||||
static std::recursive_mutex g_stream_mtx{};
|
||||
static std::recursive_mutex g_file_mtx{};
|
||||
|
||||
union Orbis__mbstate_t {
|
||||
u8 __mbstate8[128];
|
||||
@ -85,11 +85,13 @@ OrbisFILE* PS4_SYSV_ABI internal__Foprep(const char* path, const char* mode, Orb
|
||||
s32 fd, s32 flag1, s32 flag2);
|
||||
s32 PS4_SYSV_ABI internal__Fopen(const char* path, u16 mode, bool flag);
|
||||
OrbisFILE* PS4_SYSV_ABI internal_fopen(const char* path, const char* mode);
|
||||
s64 PS4_SYSV_ABI internal__Nnl(OrbisFILE* file, u8* val1, u8* val2);
|
||||
s32 PS4_SYSV_ABI internal__Fspos(OrbisFILE* file, Orbisfpos_t* file_pos, s64 offset, s32 whence);
|
||||
s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* stream);
|
||||
s32 PS4_SYSV_ABI internal_fseek(OrbisFILE* stream, s64 offset, s32 whence);
|
||||
u64 PS4_SYSV_ABI internal_fread(void* ptr, u64 size, u64 nmemb, OrbisFILE* stream);
|
||||
s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* stream);
|
||||
s32 PS4_SYSV_ABI internal_fflush(OrbisFILE* file);
|
||||
s32 PS4_SYSV_ABI internal_fseek(OrbisFILE* file, s64 offset, s32 whence);
|
||||
s32 PS4_SYSV_ABI internal__Frprep(OrbisFILE* file);
|
||||
u64 PS4_SYSV_ABI internal_fread(char* ptr, u64 size, u64 nmemb, OrbisFILE* file);
|
||||
s32 PS4_SYSV_ABI internal_fclose(OrbisFILE* file);
|
||||
|
||||
void RegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym);
|
||||
void ForceRegisterlibSceLibcInternalIo(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user