From ac556fbda9559e4a00881fa5bf6532bfc16a63a4 Mon Sep 17 00:00:00 2001 From: Marco Tylus Date: Wed, 31 Dec 2025 01:04:00 +0900 Subject: [PATCH] feat(file): implement basic SFile class functions (#110) --- storm/CMakeLists.txt | 2 + storm/file/SFileClass.cpp | 113 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 storm/file/SFileClass.cpp diff --git a/storm/CMakeLists.txt b/storm/CMakeLists.txt index 4336957..e563ed9 100644 --- a/storm/CMakeLists.txt +++ b/storm/CMakeLists.txt @@ -39,6 +39,8 @@ if(WHOA_SYSTEM_LINUX) list(APPEND STORM_SOURCES ${STORM_LINUX_SOURCES}) endif() +list(APPEND STORM_SOURCES "file/SFileClass.cpp") + if(WHOA_SFILE_MODE STREQUAL "STORMLIB") list(APPEND STORM_SOURCES "file/SFile.cpp") else() diff --git a/storm/file/SFileClass.cpp b/storm/file/SFileClass.cpp new file mode 100644 index 0000000..a7c575f --- /dev/null +++ b/storm/file/SFileClass.cpp @@ -0,0 +1,113 @@ +#include "storm/file/SFile.hpp" +#include "storm/File.hpp" +#include "storm/Memory.hpp" +#include +#include +#include + +int32_t SFile::Close(SFile* file) { + return SFileCloseFile(reinterpret_cast(file)); +} + +int32_t SFile::FileExists(const char* filename) { + HSFILE handle = nullptr; + int32_t result = SFileOpenFileEx(nullptr, filename, 0, &handle); + if (result && handle) { + SFileCloseFile(handle); + } + return result; +} + +size_t SFile::GetFileSize(SFile* file, size_t* filesizeHigh) { + uint32_t high = 0; + uint32_t low = SFileGetFileSize(reinterpret_cast(file), filesizeHigh ? &high : nullptr); + if (filesizeHigh) { + *filesizeHigh = static_cast(high); + } + + if (sizeof(size_t) > sizeof(uint32_t) && high != 0) { + return (static_cast(high) << 32) | low; + } + + return static_cast(low); +} + +int32_t SFile::IsStreamingMode() { + return 0; +} + +int32_t SFile::IsStreamingTrial() { + return 0; +} + +int32_t SFile::Load(SArchive* archive, const char* filename, void** buffer, size_t* bytes, size_t extraBytes, uint32_t flags, SOVERLAPPED* overlapped) { + (void)overlapped; + + HSFILE handle = nullptr; + if (!SFileOpenFileEx(reinterpret_cast(archive), filename, flags, &handle) || !handle) { + return 0; + } + + uint32_t high = 0; + uint32_t low = SFileGetFileSize(handle, &high); + size_t size = static_cast(low); + if (sizeof(size_t) > sizeof(uint32_t) && high != 0) { + size |= (static_cast(high) << 32); + } + + if (size > UINT32_MAX) { + SFileCloseFile(handle); + return 0; + } + + if (bytes) { + *bytes = size; + } + + char* data = new (std::nothrow) char[size + extraBytes]; + if (!data) { + SFileCloseFile(handle); + return 0; + } + + uint32_t bytesRead = 0; + int32_t result = SFileReadFile(handle, data, static_cast(size), &bytesRead, nullptr); + SFileCloseFile(handle); + + if (!result || bytesRead != size) { + STORM_FREE(data); + return 0; + } + + if (extraBytes) { + std::fill(data + size, data + size + extraBytes, 0); + } + + *buffer = data; + return 1; +} + +int32_t SFile::Open(const char* filename, SFile** file) { + return SFileOpenFileEx(nullptr, filename, 0, reinterpret_cast(file)); +} + +int32_t SFile::OpenEx(SArchive* archive, const char* filename, uint32_t flags, SFile** file) { + return SFileOpenFileEx(reinterpret_cast(archive), filename, flags, reinterpret_cast(file)); +} + +int32_t SFile::Read(SFile* file, void* buffer, size_t bytestoread, size_t* bytesread, SOVERLAPPED* overlapped, TASYNCPARAMBLOCK* asyncparam) { + (void)asyncparam; + + uint32_t toRead = bytestoread > UINT32_MAX ? UINT32_MAX : static_cast(bytestoread); + uint32_t outRead = 0; + int32_t result = SFileReadFile(reinterpret_cast(file), buffer, toRead, &outRead, reinterpret_cast(overlapped)); + if (bytesread) { + *bytesread = static_cast(outRead); + } + return result; +} + +int32_t SFile::Unload(void* ptr) { + STORM_FREE(ptr); + return 1; +}