diff --git a/storm/file/SFileNative.cpp b/storm/file/SFileNative.cpp index c137c8d..a1e85c2 100644 --- a/storm/file/SFileNative.cpp +++ b/storm/file/SFileNative.cpp @@ -1,12 +1,32 @@ #include "storm/File.hpp" +#include +#include +#include -// TODO: implement native filesystem-backed SFile functions. same functionality as whoa's SFile? +namespace { + struct NativeFileHandle { + std::ifstream stream; + std::streamsize size = 0; + }; + + std::string NormalizePath(const char* filename) { + std::string path = filename ? filename : ""; + for (char& ch : path) { + if (ch == '\\') { + ch = '/'; + } + } + return path; + } +} int32_t STORMAPI SFileOpenArchive(const char* archivename, int32_t priority, uint32_t flags, HSARCHIVE* handle) { (void)archivename; (void)priority; (void)flags; - (void)handle; + if (handle) { + *handle = nullptr; + } return 0; } @@ -17,42 +37,116 @@ int32_t STORMAPI SFileCloseArchive(HSARCHIVE handle) { int32_t STORMAPI SFileOpenFileEx(HSARCHIVE archivehandle, const char* filename, uint32_t flags, HSFILE* handle) { (void)archivehandle; - (void)filename; (void)flags; - (void)handle; - return 0; + + if (!filename || !handle) { + return 0; + } + + auto file = new NativeFileHandle(); + file->stream.open(NormalizePath(filename), std::ios::in | std::ios::binary | std::ios::ate); + + if (!file->stream.is_open()) { + delete file; + *handle = nullptr; + return 0; + } + + file->stream.seekg(0, std::ios::beg); + file->stream.ignore(std::numeric_limits::max()); + file->size = file->stream.gcount(); + file->stream.clear(); + file->stream.seekg(0, std::ios::beg); + + *handle = reinterpret_cast(file); + return 1; } int32_t STORMAPI SFileReadFile(HSFILE handle, void* buffer, uint32_t bytestoread, uint32_t* bytesread, LPOVERLAPPED overlapped) { - (void)handle; - (void)buffer; - (void)bytestoread; (void)overlapped; - if (bytesread) { - *bytesread = 0; + + if (!handle || !buffer) { + if (bytesread) { + *bytesread = 0; + } + return 0; } - return 0; + + auto file = reinterpret_cast(handle); + file->stream.read(static_cast(buffer), bytestoread); + + if (bytesread) { + *bytesread = static_cast(file->stream.gcount()); + } + + return 1; } uint32_t STORMAPI SFileGetFileSize(HSFILE handle, uint32_t* filesizehigh) { - (void)handle; - if (filesizehigh) { - *filesizehigh = 0; + if (!handle) { + if (filesizehigh) { + *filesizehigh = 0; + } + return 0; } - return 0; + + auto file = reinterpret_cast(handle); + uint64_t size = static_cast(file->size); + + if (filesizehigh) { + *filesizehigh = static_cast(size >> 32); + } + + return static_cast(size & 0xFFFFFFFFu); } uint32_t STORMAPI SFileSetFilePointer(HSFILE handle, int32_t distancetomove, int32_t* distancetomovehigh, uint32_t movemethod) { - (void)handle; - (void)distancetomove; - (void)movemethod; - if (distancetomovehigh) { - *distancetomovehigh = 0; + if (!handle) { + if (distancetomovehigh) { + *distancetomovehigh = 0; + } + return 0; } - return 0; + + int64_t offset = static_cast(distancetomove); + if (distancetomovehigh) { + offset |= (static_cast(*distancetomovehigh) << 32); + } + + std::ios_base::seekdir dir = std::ios::beg; + switch (movemethod) { + case 1: + dir = std::ios::cur; + break; + case 2: + dir = std::ios::end; + break; + default: + dir = std::ios::beg; + break; + } + + auto file = reinterpret_cast(handle); + file->stream.clear(); + file->stream.seekg(static_cast(offset), dir); + + std::streamoff pos = file->stream.tellg(); + uint64_t upos = pos < 0 ? 0 : static_cast(pos); + + if (distancetomovehigh) { + *distancetomovehigh = static_cast(upos >> 32); + } + + return static_cast(upos & 0xFFFFFFFFu); } int32_t STORMAPI SFileCloseFile(HSFILE handle) { - (void)handle; - return 0; + if (!handle) { + return 0; + } + + auto file = reinterpret_cast(handle); + file->stream.close(); + delete file; + return 1; }