diff --git a/targets/app/common/Consoles_App.cpp b/targets/app/common/Consoles_App.cpp index 77fedc5cc..444f47ef8 100644 --- a/targets/app/common/Consoles_App.cpp +++ b/targets/app/common/Consoles_App.cpp @@ -24,7 +24,7 @@ #include "app/include/NetTypes.h" #include "SkinBox.h" #include "XboxStubs.h" -#include "console_helpers/PathHelper.h" +#include "platform/PlatformServices.h" #include "java/Class.h" #include "java/File.h" #include "java/Random.h" @@ -3653,7 +3653,7 @@ void CMinecraftApp::loadMediaArchive() { if (!mediapath.empty()) { // boom headshot #if defined(__linux__) - std::wstring exeDirW = PathHelper::GetExecutableDirW(); + std::wstring exeDirW = PlatformFileIO.getBasePath().wstring(); std::wstring candidate = exeDirW + File::pathSeparator + mediapath; if (File(candidate).exists()) { m_mediaArchive = new ArchiveFile(File(candidate)); diff --git a/targets/app/common/src/Audio/SoundEngine.cpp b/targets/app/common/src/Audio/SoundEngine.cpp index fe513a3fd..d0cf17a7c 100644 --- a/targets/app/common/src/Audio/SoundEngine.cpp +++ b/targets/app/common/src/Audio/SoundEngine.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include @@ -17,7 +16,7 @@ #include "app/linux/Iggy/include/rrCore.h" #include "app/linux/Linux_App.h" #include "console_helpers/C4JThread.h" -#include "console_helpers/PathHelper.h" +#include "platform/PlatformServices.h" #include "java/Random.h" #include "minecraft/client/Minecraft.h" #include "minecraft/client/multiplayer/MultiPlayerLocalPlayer.h" @@ -184,7 +183,7 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, for (int i = 0; szId[i]; i++) if (szId[i] == '.') szId[i] = '/'; - std::string base = PathHelper::GetExecutableDirA() + "/"; + std::string base = PlatformFileIO.getBasePath().string() + "/"; const char* roots[] = { "Sound/Minecraft/", "app/common/Sound/Minecraft/", "app/common/res/TitleUpdate/res/Sound/Minecraft/"}; @@ -198,7 +197,7 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, for (int i = 1; i <= 16; i++) { char tryP[512]; snprintf(tryP, 512, "%s%s%d%s", fullRoot.c_str(), szId, i, ext); - if (std::filesystem::exists(tryP)) + if (PlatformFileIO.exists(tryP)) count = i; else break; @@ -211,7 +210,7 @@ void SoundEngine::play(int iSound, float x, float y, float z, float volume, } char tryP[512]; snprintf(tryP, 512, "%s%s%s", fullRoot.c_str(), szId, ext); - if (std::filesystem::exists(tryP)) { + if (PlatformFileIO.exists(tryP)) { strncpy(finalPath, tryP, 511); found = true; break; @@ -251,7 +250,7 @@ void SoundEngine::playUI(int iSound, float volume, float pitch) { wcstombs(szIdentifier, wchUISoundNames[iSound], 255); for (int i = 0; szIdentifier[i]; i++) if (szIdentifier[i] == '.') szIdentifier[i] = '/'; - std::string base = PathHelper::GetExecutableDirA() + "/"; + std::string base = PlatformFileIO.getBasePath().string() + "/"; const char* roots[] = { "Sound/Minecraft/UI/", "Sound/Minecraft/", @@ -266,7 +265,7 @@ void SoundEngine::playUI(int iSound, float volume, float pitch) { char tryP[512]; snprintf(tryP, 512, "%s%s%s%s", base.c_str(), root, szIdentifier, ext); - if (std::filesystem::exists(tryP)) { + if (PlatformFileIO.exists(tryP)) { strncpy(finalPath, tryP, 511); found = true; break; @@ -453,7 +452,7 @@ void SoundEngine::playMusicTick() { return; } if (m_musicID != -1) { - std::string base = PathHelper::GetExecutableDirA() + "/"; + std::string base = PlatformFileIO.getBasePath().string() + "/"; bool isCD = (m_musicID >= m_iStream_CD_1); const char* folder = isCD ? "cds/" : "music/"; const char* track = m_szStreamFileA[m_musicID]; @@ -469,14 +468,14 @@ void SoundEngine::playMusicTick() { // try with folder prefix (music/ or cds/) snprintf(c, 512, "%s%s%s%s%s", base.c_str(), r, folder, track, e); - if (std::filesystem::exists(c)) { + if (PlatformFileIO.exists(c)) { strncpy(m_szStreamName, c, 511); found = true; break; } // try without folder prefix snprintf(c, 512, "%s%s%s%s", base.c_str(), r, track, e); - if (std::filesystem::exists(c)) { + if (PlatformFileIO.exists(c)) { strncpy(m_szStreamName, c, 511); found = true; break; diff --git a/targets/app/common/src/DLC/DLCManager.cpp b/targets/app/common/src/DLC/DLCManager.cpp index 6f216b25d..8bc2270db 100644 --- a/targets/app/common/src/DLC/DLCManager.cpp +++ b/targets/app/common/src/DLC/DLCManager.cpp @@ -20,7 +20,7 @@ #include "app/common/src/GameRules/GameRuleManager.h" #include "app/linux/Linux_App.h" #include "app/linux/Linux_UIController.h" -#include "console_helpers/PortableFileIO.h" +#include "platform/PlatformServices.h" #include "console_helpers/StringHelpers.h" #include "minecraft/client/Minecraft.h" #include "minecraft/client/skins/TexturePackRepository.h" @@ -105,40 +105,20 @@ bool readOwnedDlcFile(const std::string& path, std::uint8_t** ppData, *pBytesRead = 0; const std::wstring readPath = getMountedDlcReadPath(path); - std::FILE* file = PortableFileIO::OpenBinaryFileForRead(readPath); - if (file == nullptr) { + const std::size_t fSize = PlatformFileIO.fileSize(readPath); + if (fSize == 0 || fSize > std::numeric_limits::max()) { return false; } - if (!PortableFileIO::Seek(file, 0, SEEK_END)) { - std::fclose(file); - return false; - } - - const int64_t endPosition = PortableFileIO::Tell(file); - if (endPosition <= 0 || - endPosition > std::numeric_limits::max()) { - std::fclose(file); - return false; - } - - const unsigned int fileSize = static_cast(endPosition); - if (!PortableFileIO::Seek(file, 0, SEEK_SET)) { - std::fclose(file); - return false; - } - - std::uint8_t* data = new std::uint8_t[fileSize]; - const std::size_t bytesRead = std::fread(data, 1, fileSize, file); - const bool failed = std::ferror(file) != 0 || bytesRead != fileSize; - std::fclose(file); - if (failed) { + std::uint8_t* data = new std::uint8_t[fSize]; + auto result = PlatformFileIO.readFile(readPath, data, fSize); + if (result.status != IPlatformFileIO::ReadStatus::Ok) { delete[] data; return false; } *ppData = data; - *pBytesRead = static_cast(bytesRead); + *pBytesRead = static_cast(result.bytesRead); return true; } } // namespace @@ -398,7 +378,8 @@ unsigned int DLCManager::checkForCorruptDLCAndAlert( bool DLCManager::readDLCDataFile(unsigned int& dwFilesProcessed, const std::wstring& path, DLCPack* pack, bool fromArchive) { - return readDLCDataFile(dwFilesProcessed, wstringtofilename(path), pack, + return readDLCDataFile(dwFilesProcessed, + std::filesystem::path(path).string(), pack, fromArchive); } diff --git a/targets/app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.cpp b/targets/app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.cpp index a6d3baa7e..121ed4ebd 100644 --- a/targets/app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.cpp +++ b/targets/app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.cpp @@ -3,8 +3,6 @@ #include #include -#include -#include #include #include @@ -25,6 +23,7 @@ #include "app/linux/Linux_App.h" #include "app/linux/Stubs/winapi_stubs.h" #include "console_helpers/StringHelpers.h" +#include "platform/PlatformServices.h" #include "java/File.h" #include "java/InputOutputStream/ByteArrayInputStream.h" #include "java/InputOutputStream/DataInputStream.h" @@ -521,16 +520,13 @@ int LevelGenerationOptions::packMounted(void* pParam, int iPad, uint32_t dwErr, dlcFile->getGrfPath(), true, L"WPACK:")); if (grf.exists()) { - std::filesystem::path grfPath = grf.getPath(); - std::ifstream fileHandle(grfPath, std::ios::binary); - - if (fileHandle) { - uint32_t dwFileSize = grf.length(); + uint32_t dwFileSize = grf.length(); + if (dwFileSize > 0) { uint8_t* pbData = (uint8_t*)new uint8_t[dwFileSize]; - fileHandle.read( - reinterpret_cast(pbData), - static_cast(dwFileSize)); - if (!fileHandle) { + auto readResult = PlatformFileIO.readFile( + grf.getPath(), pbData, dwFileSize); + if (readResult.status != + IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); } @@ -550,15 +546,14 @@ int LevelGenerationOptions::packMounted(void* pParam, int iPad, uint32_t dwErr, File save(app.getFilePath(lgo->m_parentDLCPack->GetPackID(), lgo->getBaseSavePath(), true, L"WPACK:")); if (save.exists()) { - std::filesystem::path savePath = save.getPath(); - std::ifstream saveHandle(savePath, std::ios::binary); - - if (saveHandle) { - auto dwFileSize = std::filesystem::file_size(savePath); + std::size_t dwFileSize = + PlatformFileIO.fileSize(save.getPath()); + if (dwFileSize > 0) { uint8_t* pbData = (uint8_t*)new uint8_t[dwFileSize]; - saveHandle.read(reinterpret_cast(pbData), - static_cast(dwFileSize)); - if (!saveHandle) { + auto readResult = PlatformFileIO.readFile( + save.getPath(), pbData, dwFileSize); + if (readResult.status != + IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); } diff --git a/targets/app/common/src/Network/GameNetworkManager.cpp b/targets/app/common/src/Network/GameNetworkManager.cpp index 920f872d2..babdc3d96 100644 --- a/targets/app/common/src/Network/GameNetworkManager.cpp +++ b/targets/app/common/src/Network/GameNetworkManager.cpp @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include #include #include @@ -30,6 +28,7 @@ #include "Socket.h" #include "XboxStubs.h" #include "console_helpers/StringHelpers.h" +#include "platform/PlatformServices.h" #include "console_helpers/ThreadName.h" #include "console_helpers/compression.h" #include "java/File.h" @@ -161,18 +160,15 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft, #endif File grf(fileRoot); if (grf.exists()) { - std::filesystem::path grfPath = grf.getPath(); - std::ifstream fileHandle(grfPath, std::ios::binary); - - if (fileHandle) { - auto dwFileSize = - std::filesystem::file_size(grfPath); + std::size_t dwFileSize = + PlatformFileIO.fileSize(grf.getPath()); + if (dwFileSize > 0) { uint8_t* pbData = (uint8_t*)new uint8_t[dwFileSize]; - fileHandle.read( - reinterpret_cast(pbData), - static_cast(dwFileSize)); - if (!fileHandle) { + auto readResult = PlatformFileIO.readFile( + grf.getPath(), pbData, dwFileSize); + if (readResult.status != + IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); } diff --git a/targets/app/common/src/UI/All Platforms/ArchiveFile.cpp b/targets/app/common/src/UI/All Platforms/ArchiveFile.cpp index 757dd27e8..fb30fa7b4 100644 --- a/targets/app/common/src/UI/All Platforms/ArchiveFile.cpp +++ b/targets/app/common/src/UI/All Platforms/ArchiveFile.cpp @@ -7,7 +7,7 @@ #include "app/linux/Linux_App.h" #include "app/linux/Stubs/winapi_stubs.h" -#include "console_helpers/PortableFileIO.h" +#include "platform/PlatformServices.h" #include "console_helpers/compression.h" #include "java/InputOutputStream/ByteArrayInputStream.h" #include "java/InputOutputStream/DataInputStream.h" @@ -116,12 +116,12 @@ std::vector ArchiveFile::getFile(const std::wstring& filename) { const unsigned int fileSize = static_cast(data->filesize); std::uint8_t* pbData = new std::uint8_t[fileSize == 0 ? 1 : fileSize]; out = std::vector(pbData, pbData + fileSize); - const PortableFileIO::BinaryReadResult readResult = - PortableFileIO::ReadBinaryFileSegment( + auto readResult = + PlatformFileIO.readFileSegment( m_sourcefile.getPath(), static_cast(data->ptr), out.data(), static_cast(data->filesize)); - if (readResult.status != PortableFileIO::BinaryReadStatus::ok) { + if (readResult.status != IPlatformFileIO::ReadStatus::Ok) { app.DebugPrintf("Failed to read archive file segment\n"); app.FatalLoadError(); } diff --git a/targets/app/common/src/UI/UITTFFont.cpp b/targets/app/common/src/UI/UITTFFont.cpp index fb7a1a97e..dc8ce76cc 100644 --- a/targets/app/common/src/UI/UITTFFont.cpp +++ b/targets/app/common/src/UI/UITTFFont.cpp @@ -2,16 +2,14 @@ #include -#include - #include "app/linux/Iggy/include/iggy.h" #ifndef _ENABLEIGGY #include "app/linux/Stubs/iggy_stubs.h" #endif #include "app/linux/Iggy/include/rrCore.h" #include "app/linux/Linux_App.h" -#include "console_helpers/PortableFileIO.h" #include "console_helpers/StringHelpers.h" +#include "platform/PlatformServices.h" UITTFFont::UITTFFont(const std::string& name, const std::string& path, S32 fallbackCharacter) @@ -19,36 +17,14 @@ UITTFFont::UITTFFont(const std::string& name, const std::string& path, app.DebugPrintf("UITTFFont opening %s\n", path.c_str()); pbData = nullptr; - std::wstring wPath = convStringToWstring(path); - std::FILE* file = PortableFileIO::OpenBinaryFileForRead(wPath); - if (file == nullptr) { - app.DebugPrintf("Failed to open TTF file\n"); - assert(false); - } - - if (!PortableFileIO::Seek(file, 0, SEEK_END)) { - std::fclose(file); - app.FatalLoadError(); - } - - const int64_t endPosition = PortableFileIO::Tell(file); - if (endPosition < 0) { - std::fclose(file); - app.FatalLoadError(); - } - - const std::size_t fileSize = static_cast(endPosition); + const std::size_t fileSize = PlatformFileIO.fileSize(path); if (fileSize != 0) { - if (!PortableFileIO::Seek(file, 0, SEEK_SET)) { - std::fclose(file); - app.FatalLoadError(); - } - pbData = new std::uint8_t[fileSize]; - const std::size_t bytesRead = std::fread(pbData, 1, fileSize, file); - const bool failed = std::ferror(file) != 0 || bytesRead != fileSize; - std::fclose(file); - if (failed) { + auto result = PlatformFileIO.readFile(path, pbData, fileSize); + if (result.status != IPlatformFileIO::ReadStatus::Ok) { + app.DebugPrintf("Failed to open TTF file\n"); + delete[] pbData; + pbData = nullptr; app.FatalLoadError(); } @@ -65,7 +41,8 @@ UITTFFont::UITTFFont(const std::string& name, const std::string& path, IggyFontInstallTruetypeUTF8((void*)pbData, IGGY_TTC_INDEX_none, "Arial", -1, IGGY_FONTFLAG_none); } else { - std::fclose(file); + app.DebugPrintf("Failed to open TTF file\n"); + assert(false); } } diff --git a/targets/app/src/BufferedImage.cpp b/targets/app/src/BufferedImage.cpp index 7a3ff7c9d..fd60333bb 100644 --- a/targets/app/src/BufferedImage.cpp +++ b/targets/app/src/BufferedImage.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -14,8 +13,8 @@ #include "app/linux/Linux_App.h" #include "app/linux/Stubs/winapi_stubs.h" #include "PlatformTypes.h" -#include "console_helpers/PathHelper.h" #include "console_helpers/StringHelpers.h" +#include "platform/PlatformServices.h" BufferedImage::BufferedImage(int width, int height, int type) { data[0] = new int[width * height]; @@ -62,7 +61,7 @@ BufferedImage::BufferedImage(const std::wstring& File, baseName = baseName.substr(1); if (baseName.find(L"res/") == 0) baseName = baseName.substr(4); - std::wstring exeDir = PathHelper::GetExecutableDirW(); + std::wstring exeDir = PlatformFileIO.getBasePath().wstring(); for (int l = 0; l < 10; l++) { std::wstring mipSuffix = @@ -83,7 +82,7 @@ BufferedImage::BufferedImage(const std::wstring& File, size_t p; while ((p = attempt.find(L"//")) != std::wstring::npos) attempt.replace(p, 2, L"/"); - if (std::filesystem::exists(wstringtofilename(attempt))) { + if (PlatformFileIO.exists(attempt)) { finalPath = attempt; foundOnDisk = true; break; @@ -94,7 +93,8 @@ BufferedImage::BufferedImage(const std::wstring& File, memset(&ImageInfo, 0, sizeof(D3DXIMAGE_INFO)); if (foundOnDisk) { - hr = RenderManager.LoadTextureData(wstringtofilename(finalPath), + std::string nativePath = std::filesystem::path(finalPath).string(); + hr = RenderManager.LoadTextureData(nativePath.c_str(), &ImageInfo, &data[l]); } else { std::wstring archiveKey = L"res/" + fileName; diff --git a/targets/console_helpers/include/console_helpers/PathHelper.h b/targets/console_helpers/include/console_helpers/PathHelper.h deleted file mode 100644 index f6933cb1f..000000000 --- a/targets/console_helpers/include/console_helpers/PathHelper.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#include -#if defined(__linux__) -#include -#include -#endif - -namespace PathHelper { -inline std::wstring GetExecutableDirW() { -#if defined(__linux__) - char buffer[4096]; - ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); - if (len != -1) { - buffer[len] = '\0'; - std::string path(buffer); - size_t lastSlash = path.find_last_of('/'); - if (lastSlash != std::string::npos) - return std::wstring(path.begin(), path.begin() + lastSlash); - } -#endif - return L"."; -} - -inline std::string GetExecutableDirA() { -#if defined(__linux__) - char buffer[4096]; - ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); - if (len != -1) { - buffer[len] = '\0'; - std::string path(buffer); - size_t lastSlash = path.find_last_of('/'); - if (lastSlash != std::string::npos) return path.substr(0, lastSlash); - } -#endif - return "."; -} -} // namespace PathHelper \ No newline at end of file diff --git a/targets/console_helpers/include/console_helpers/PortableFileIO.h b/targets/console_helpers/include/console_helpers/PortableFileIO.h deleted file mode 100644 index 0c4256a06..000000000 --- a/targets/console_helpers/include/console_helpers/PortableFileIO.h +++ /dev/null @@ -1,146 +0,0 @@ -#pragma once - -#include -#include -#include - -#include "console_helpers/StringHelpers.h" - -namespace PortableFileIO { -enum class BinaryReadStatus { - ok, - not_found, - too_large, - read_error, -}; - -struct BinaryReadResult { - BinaryReadStatus status; - std::size_t bytesRead; - std::size_t fileSize; -}; - -inline std::FILE* OpenBinaryFileForRead(const std::wstring& path) { -#if defined(_WIN32) - return _wfopen(path.c_str(), L"rb"); -#else - const std::string nativePath = wstringtofilename(path); - return std::fopen(nativePath.c_str(), "rb"); -#endif -} - -inline bool Seek(std::FILE* file, std::size_t offset, int origin) { -#if defined(_WIN32) - return _fseeki64(file, static_cast(offset), origin) == 0; -#else - return fseeko(file, static_cast(offset), origin) == 0; -#endif -} - -inline int64_t Tell(std::FILE* file) { -#if defined(_WIN32) - return _ftelli64(file); -#else - return static_cast(ftello(file)); -#endif -} - -inline BinaryReadResult ReadBinaryFile(const std::wstring& path, void* buffer, - std::size_t capacity) { - std::FILE* stream = OpenBinaryFileForRead(path); - if (stream == nullptr) { - return {BinaryReadStatus::not_found, 0, 0}; - } - - if (!Seek(stream, 0, SEEK_END)) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, 0}; - } - - const int64_t endPosition = Tell(stream); - if (endPosition < 0) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, 0}; - } - - const std::size_t fileSize = static_cast(endPosition); - if (fileSize > capacity) { - std::fclose(stream); - return {BinaryReadStatus::too_large, 0, fileSize}; - } - - if (!Seek(stream, 0, SEEK_SET)) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, fileSize}; - } - - const std::size_t bytesRead = std::fread(buffer, 1, fileSize, stream); - const bool failed = std::ferror(stream) != 0; - std::fclose(stream); - if (failed || bytesRead != fileSize) { - return {BinaryReadStatus::read_error, bytesRead, fileSize}; - } - - return {BinaryReadStatus::ok, bytesRead, fileSize}; -} - -inline BinaryReadResult ReadBinaryFileSegment(const std::wstring& path, - std::size_t offset, void* buffer, - std::size_t bytesToRead) { - std::FILE* stream = OpenBinaryFileForRead(path); - if (stream == nullptr) { - return {BinaryReadStatus::not_found, 0, 0}; - } - - if (!Seek(stream, 0, SEEK_END)) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, 0}; - } - - const int64_t endPosition = Tell(stream); - if (endPosition < 0) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, 0}; - } - - const std::size_t fileSize = static_cast(endPosition); - if ((offset > fileSize) || (bytesToRead > (fileSize - offset))) { - std::fclose(stream); - return {BinaryReadStatus::too_large, 0, fileSize}; - } - - if (!Seek(stream, offset, SEEK_SET)) { - std::fclose(stream); - return {BinaryReadStatus::read_error, 0, fileSize}; - } - - const std::size_t bytesRead = std::fread(buffer, 1, bytesToRead, stream); - const bool failed = std::ferror(stream) != 0; - std::fclose(stream); - if (failed || bytesRead != bytesToRead) { - return {BinaryReadStatus::read_error, bytesRead, fileSize}; - } - - return {BinaryReadStatus::ok, bytesRead, fileSize}; -} - -inline bool WriteBinaryFile(const std::wstring& path, const void* buffer, - std::size_t bytesToWrite) { -#if defined(_WIN32) - std::FILE* stream = _wfopen(path.c_str(), L"wb"); -#else - const std::string nativePath = wstringtofilename(path); - std::FILE* stream = std::fopen(nativePath.c_str(), "wb"); -#endif - if (stream == nullptr) { - return false; - } - - const std::size_t bytesWritten = - std::fwrite(buffer, 1, bytesToWrite, stream); - const bool failed = - std::ferror(stream) != 0 || bytesWritten != bytesToWrite; - const bool closeFailed = std::fclose(stream) != 0; - return !failed && !closeFailed; -} -} // namespace PortableFileIO diff --git a/targets/java/meson.build b/targets/java/meson.build index cf434f056..5e489f82f 100644 --- a/targets/java/meson.build +++ b/targets/java/meson.build @@ -26,7 +26,7 @@ lib_java = static_library('java', java_sources, dependencies: [console_helpers_dep], # TODO: remove the .. path once arrayWithLength are evaporated - include_directories: include_directories('include'), + include_directories: include_directories('include', '..'), cpp_args : global_cpp_args + global_cpp_defs, ) diff --git a/targets/java/src/File.cpp b/targets/java/src/File.cpp index b2e2665f7..b1036d281 100644 --- a/targets/java/src/File.cpp +++ b/targets/java/src/File.cpp @@ -8,8 +8,8 @@ #include #include -#include "console_helpers/PathHelper.h" // 4jcraft TODO #include "console_helpers/StringHelpers.h" // 4jcraft TODO +#include "platform/PlatformServices.h" #include "java/FileFilter.h" const wchar_t File::pathSeparator = L'/'; @@ -21,8 +21,7 @@ namespace { namespace fs = std::filesystem; fs::path ToFilesystemPath(const std::wstring& path) { - const std::string nativePath = wstringtofilename(path); - return fs::path(nativePath); + return fs::path(path); } std::wstring ToFilename(const fs::path& path) { @@ -65,11 +64,11 @@ File::File(const std::wstring& pathname) { m_abstractPathName = fixedPath; #if defined(__linux__) - std::string request = wstringtofilename(m_abstractPathName); + std::string request = std::filesystem::path(m_abstractPathName).string(); while (!request.empty() && request[0] == '/') request.erase(0, 1); if (request.find("res/") == 0) request.erase(0, 4); - std::string exeDir = PathHelper::GetExecutableDirA(); + std::string exeDir = PlatformFileIO.getBasePath().string(); std::string fileName = request; size_t lastSlash = fileName.find_last_of('/'); if (lastSlash != std::string::npos) @@ -85,11 +84,11 @@ File::File(const std::wstring& pathname) { for (const char* base : bases) { std::string tryFull = exeDir + base + request; std::string tryFile = exeDir + base + fileName; - if (std::filesystem::exists(tryFull)) { + if (PlatformFileIO.exists(tryFull)) { m_abstractPathName = convStringToWstring(tryFull); return; } - if (std::filesystem::exists(tryFile)) { + if (PlatformFileIO.exists(tryFile)) { m_abstractPathName = convStringToWstring(tryFile); return; } @@ -97,7 +96,7 @@ File::File(const std::wstring& pathname) { #endif #ifdef _WINDOWS64 - std::string path = wstringtofilename(m_abstractPathName); + std::string path = std::filesystem::path(m_abstractPathName).string(); std::string finalPath = StorageManager.GetMountedPath(path.c_str()); if (finalPath.size() == 0) finalPath = path; m_abstractPathName = convStringToWstring(finalPath); diff --git a/targets/java/src/InputOutputStream/FileInputStream.cpp b/targets/java/src/InputOutputStream/FileInputStream.cpp index 141958d8e..71e86f539 100644 --- a/targets/java/src/InputOutputStream/FileInputStream.cpp +++ b/targets/java/src/InputOutputStream/FileInputStream.cpp @@ -10,7 +10,8 @@ #include #include -#include "console_helpers/StringHelpers.h" +#include + #include "java/File.h" namespace { @@ -52,7 +53,7 @@ FileInputStream::FileInputStream(const File& file) : m_fileHandle(nullptr) { #if defined(_WIN32) m_fileHandle = _wfopen(file.getPath().c_str(), L"rb"); #else - const std::string nativePath = wstringtofilename(file.getPath()); + const std::string nativePath = std::filesystem::path(file.getPath()).string(); m_fileHandle = std::fopen(nativePath.c_str(), "rb"); #endif diff --git a/targets/java/src/InputOutputStream/FileOutputStream.cpp b/targets/java/src/InputOutputStream/FileOutputStream.cpp index a1e452784..a52b6a7d7 100644 --- a/targets/java/src/InputOutputStream/FileOutputStream.cpp +++ b/targets/java/src/InputOutputStream/FileOutputStream.cpp @@ -5,7 +5,8 @@ #include #include -#include "console_helpers/StringHelpers.h" // 4jcraft TODO +#include + #include "java/File.h" // Creates a file output stream to write to the file represented by the @@ -29,7 +30,7 @@ FileOutputStream::FileOutputStream(const File& file) : m_fileHandle(nullptr) { #if defined(_WIN32) m_fileHandle = _wfopen(file.getPath().c_str(), L"wb"); #else - const std::string nativePath = wstringtofilename(file.getPath()); + const std::string nativePath = std::filesystem::path(file.getPath()).string(); m_fileHandle = std::fopen(nativePath.c_str(), "wb"); #endif diff --git a/targets/minecraft/client/skins/DLCTexturePack.cpp b/targets/minecraft/client/skins/DLCTexturePack.cpp index 76e9e7f43..81d6fdb3c 100644 --- a/targets/minecraft/client/skins/DLCTexturePack.cpp +++ b/targets/minecraft/client/skins/DLCTexturePack.cpp @@ -27,7 +27,7 @@ #include "app/linux/Linux_UIController.h" #include "app/linux/Stubs/winapi_stubs.h" #include "app/include/BufferedImage.h" -#include "console_helpers/PortableFileIO.h" +#include "platform/PlatformServices.h" #include "java/File.h" #include "minecraft/client/Minecraft.h" #include "minecraft/client/skins/AbstractTexturePack.h" @@ -52,9 +52,9 @@ bool ReadPortableBinaryFile(File& file, std::uint8_t*& data, const std::size_t capacity = static_cast(fileLength); std::uint8_t* buffer = new std::uint8_t[capacity == 0 ? 1 : capacity]; - const PortableFileIO::BinaryReadResult readResult = - PortableFileIO::ReadBinaryFile(file.getPath(), buffer, capacity); - if (readResult.status != PortableFileIO::BinaryReadStatus::ok || + auto readResult = + PlatformFileIO.readFile(file.getPath(), buffer, capacity); + if (readResult.status != IPlatformFileIO::ReadStatus::Ok || readResult.fileSize > std::numeric_limits::max()) { delete[] buffer; data = nullptr; diff --git a/targets/minecraft/world/level/chunk/storage/NbtSlotFile.cpp b/targets/minecraft/world/level/chunk/storage/NbtSlotFile.cpp index 7f93364c2..d45069c35 100644 --- a/targets/minecraft/world/level/chunk/storage/NbtSlotFile.cpp +++ b/targets/minecraft/world/level/chunk/storage/NbtSlotFile.cpp @@ -1,5 +1,7 @@ #include "NbtSlotFile.h" +#include + #include "java/File.h" namespace { @@ -10,7 +12,7 @@ std::FILE* OpenBinaryFileForReadWrite(const File& file) { stream = _wfopen(file.getPath().c_str(), L"w+b"); } #else - const std::string nativePath = wstringtofilename(file.getPath()); + const std::string nativePath = std::filesystem::path(file.getPath()).string(); std::FILE* stream = std::fopen(nativePath.c_str(), "r+b"); if (stream == nullptr) { stream = std::fopen(nativePath.c_str(), "w+b"); diff --git a/targets/minecraft/world/level/chunk/storage/ZoneFile.cpp b/targets/minecraft/world/level/chunk/storage/ZoneFile.cpp index 06f70c1b1..deff8d4df 100644 --- a/targets/minecraft/world/level/chunk/storage/ZoneFile.cpp +++ b/targets/minecraft/world/level/chunk/storage/ZoneFile.cpp @@ -1,5 +1,7 @@ #include "ZoneFile.h" +#include + #include "java/ByteBuffer.h" #include "java/File.h" @@ -11,7 +13,7 @@ std::FILE* OpenBinaryFileForReadWrite(const File& file) { stream = _wfopen(file.getPath().c_str(), L"w+b"); } #else - const std::string nativePath = wstringtofilename(file.getPath()); + const std::string nativePath = std::filesystem::path(file.getPath()).string(); std::FILE* stream = std::fopen(nativePath.c_str(), "r+b"); if (stream == nullptr) { stream = std::fopen(nativePath.c_str(), "w+b"); diff --git a/targets/minecraft/world/level/chunk/storage/ZonedChunkStorage.cpp b/targets/minecraft/world/level/chunk/storage/ZonedChunkStorage.cpp index 7a057560b..e96629b09 100644 --- a/targets/minecraft/world/level/chunk/storage/ZonedChunkStorage.cpp +++ b/targets/minecraft/world/level/chunk/storage/ZonedChunkStorage.cpp @@ -1,5 +1,6 @@ #include "ZonedChunkStorage.h" +#include #include #include "ZoneFile.h" @@ -66,7 +67,7 @@ ZoneFile* ZonedChunkStorage::getZoneFile(int x, int z, bool create) { if (!file.exists()) { if (!create) return nullptr; - void* ch = CreateFile(wstringtofilename(file.getPath()), + void* ch = CreateFile(std::filesystem::path(file.getPath()).string().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); CloseHandle(ch); diff --git a/targets/minecraft/world/level/levelgen/CustomLevelSource.cpp b/targets/minecraft/world/level/levelgen/CustomLevelSource.cpp index 531fa319f..14ae35a4d 100644 --- a/targets/minecraft/world/level/levelgen/CustomLevelSource.cpp +++ b/targets/minecraft/world/level/levelgen/CustomLevelSource.cpp @@ -4,11 +4,9 @@ #include #include -#include -#include - #include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h" #include "app/linux/Linux_App.h" +#include "platform/PlatformServices.h" #include "minecraft/world/level/biome/Biome.h" #include "minecraft/world/level/chunk/ChunkSource.h" #if defined(__linux__) @@ -45,45 +43,34 @@ CustomLevelSource::CustomLevelSource(Level* level, int64_t seed, m_heightmapOverride = std::vector((m_XZSize * 16) * (m_XZSize * 16)); - std::filesystem::path path = "GameRules/heightmap.bin"; - std::ifstream file(path, std::ios::binary); - if (!file) { - app.FatalLoadError(); - assert(false); - } else { - auto fileSize = std::filesystem::file_size(path); - if (fileSize > m_heightmapOverride.size()) { + { + const char* path = "GameRules/heightmap.bin"; + auto result = PlatformFileIO.readFile( + path, m_heightmapOverride.data(), m_heightmapOverride.size()); + if (result.status == IPlatformFileIO::ReadStatus::TooLarge) { app.DebugPrintf("Heightmap binary is too large!!\n"); __debugbreak(); - } - file.read(reinterpret_cast(m_heightmapOverride.data()), - static_cast(fileSize)); - - if (!file) { + } else if (result.status != IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); + assert(false); } } m_waterheightOverride = std::vector((m_XZSize * 16) * (m_XZSize * 16)); - std::filesystem::path waterHeightPath = "GameRules/waterheight.bin"; - std::ifstream waterHeightFile(waterHeightPath, std::ios::binary); - if (!waterHeightFile) { - // assert(false); - memset(m_waterheightOverride.data(), level->seaLevel, - m_waterheightOverride.size()); - } else { - auto waterFileSize = std::filesystem::file_size(waterHeightPath); - if (waterFileSize > m_waterheightOverride.size()) { + { + const char* waterHeightPath = "GameRules/waterheight.bin"; + auto result = PlatformFileIO.readFile( + waterHeightPath, m_waterheightOverride.data(), + m_waterheightOverride.size()); + if (result.status == IPlatformFileIO::ReadStatus::NotFound) { + memset(m_waterheightOverride.data(), level->seaLevel, + m_waterheightOverride.size()); + } else if (result.status == IPlatformFileIO::ReadStatus::TooLarge) { app.DebugPrintf("waterheight binary is too large!!\n"); __debugbreak(); - } - waterHeightFile.read( - reinterpret_cast(m_waterheightOverride.data()), - static_cast(waterFileSize)); - - if (!waterHeightFile) { + } else if (result.status != IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); } } diff --git a/targets/minecraft/world/level/newbiome/layer/BiomeOverrideLayer.cpp b/targets/minecraft/world/level/newbiome/layer/BiomeOverrideLayer.cpp index e5e1cf371..8abde4119 100644 --- a/targets/minecraft/world/level/newbiome/layer/BiomeOverrideLayer.cpp +++ b/targets/minecraft/world/level/newbiome/layer/BiomeOverrideLayer.cpp @@ -2,10 +2,8 @@ #include -#include -#include - #include "app/linux/Linux_App.h" +#include "platform/PlatformServices.h" #include "minecraft/world/level/newbiome/layer/Layer.h" #if defined(__linux__) #include "app/linux/Stubs/winapi_stubs.h" @@ -15,24 +13,18 @@ BiomeOverrideLayer::BiomeOverrideLayer(int seedMixup) : Layer(seedMixup) { m_biomeOverride = std::vector(width * height); - std::filesystem::path path = "GameRules/biomemap.bin"; - std::ifstream file(path, std::ios::binary); - if (!file) { - // assert(false); - app.DebugPrintf("Biome override not found, using plains as default\n"); - - memset(m_biomeOverride.data(), Biome::plains->id, - m_biomeOverride.size()); - } else { - auto fileSize = std::filesystem::file_size(path); - if (fileSize > m_biomeOverride.size()) { + { + const char* path = "GameRules/biomemap.bin"; + auto result = PlatformFileIO.readFile( + path, m_biomeOverride.data(), m_biomeOverride.size()); + if (result.status == IPlatformFileIO::ReadStatus::NotFound) { + app.DebugPrintf("Biome override not found, using plains as default\n"); + memset(m_biomeOverride.data(), Biome::plains->id, + m_biomeOverride.size()); + } else if (result.status == IPlatformFileIO::ReadStatus::TooLarge) { app.DebugPrintf("Biomemap binary is too large!!\n"); __debugbreak(); - } - file.read(reinterpret_cast(m_biomeOverride.data()), - static_cast(fileSize)); - - if (!file) { + } else if (result.status != IPlatformFileIO::ReadStatus::Ok) { app.FatalLoadError(); } } diff --git a/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileOriginal.cpp b/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileOriginal.cpp index 5e49d6ba3..9df39c8f9 100644 --- a/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileOriginal.cpp +++ b/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileOriginal.cpp @@ -18,7 +18,6 @@ #include "app/common/src/GameRules/LevelGeneration/LevelGenerationOptions.h" #include "app/linux/Linux_App.h" #include "app/linux/Stubs/winapi_stubs.h" -#include "console_helpers/PortableFileIO.h" #include "console_helpers/compression.h" #include "java/File.h" #include "java/InputOutputStream/DataInputStream.h" @@ -744,13 +743,13 @@ void ConsoleSaveFileOriginal::DebugFlushToFile( bool writeSucceeded = false; if (compressedData != nullptr && compressedDataSize > 0) { - writeSucceeded = PortableFileIO::WriteBinaryFile( + writeSucceeded = PlatformFileIO.writeFile( outputPath, compressedData, compressedDataSize); numberOfBytesWritten = writeSucceeded ? compressedDataSize : 0; assert(numberOfBytesWritten == compressedDataSize); } else { writeSucceeded = - PortableFileIO::WriteBinaryFile(outputPath, pvSaveMem, fileSize); + PlatformFileIO.writeFile(outputPath, pvSaveMem, fileSize); numberOfBytesWritten = writeSucceeded ? fileSize : 0; assert(numberOfBytesWritten == fileSize); } diff --git a/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileSplit.cpp b/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileSplit.cpp index aaaf0610b..ab78f75eb 100644 --- a/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileSplit.cpp +++ b/targets/minecraft/world/level/storage/ConsoleSaveFileIO/ConsoleSaveFileSplit.cpp @@ -20,7 +20,6 @@ #include "app/linux/Linux_App.h" #include "app/linux/Stubs/winapi_stubs.h" #include "console_helpers/PlatformTime.h" -#include "console_helpers/PortableFileIO.h" #include "console_helpers/StringHelpers.h" #include "console_helpers/compression.h" #include "java/File.h" @@ -1469,13 +1468,13 @@ void ConsoleSaveFileSplit::DebugFlushToFile( bool writeSucceeded = false; if (compressedData != nullptr && compressedDataSize > 0) { - writeSucceeded = PortableFileIO::WriteBinaryFile( + writeSucceeded = PlatformFileIO.writeFile( outputPath, compressedData, compressedDataSize); numberOfBytesWritten = writeSucceeded ? compressedDataSize : 0; assert(numberOfBytesWritten == compressedDataSize); } else { writeSucceeded = - PortableFileIO::WriteBinaryFile(outputPath, pvSaveMem, fileSize); + PlatformFileIO.writeFile(outputPath, pvSaveMem, fileSize); numberOfBytesWritten = writeSucceeded ? fileSize : 0; assert(numberOfBytesWritten == fileSize); } diff --git a/targets/platform/PlatformServices.cpp b/targets/platform/PlatformServices.cpp index a79ff20d3..01da05027 100644 --- a/targets/platform/PlatformServices.cpp +++ b/targets/platform/PlatformServices.cpp @@ -1,15 +1,14 @@ #include "PlatformServices.h" +#include "StdFileIO.h" -#include "../platform/sdl2/Input.h" -#include "../platform/sdl2/Profile.h" -#include "../platform/sdl2/Render.h" -#include "../platform/sdl2/Storage.h" +#include "sdl2/Input.h" +#include "sdl2/Profile.h" +#include "sdl2/Render.h" +#include "sdl2/Storage.h" -class IPlatformInput; -class IPlatformProfile; -class IPlatformRenderer; -class IPlatformStorage; +static StdFileIO s_stdFileIO; +IPlatformFileIO& PlatformFileIO = s_stdFileIO; IPlatformInput& PlatformInput = InputManager; IPlatformProfile& PlatformProfile = ProfileManager; IPlatformRenderer& PlatformRender = RenderManager; diff --git a/targets/platform/PlatformServices.h b/targets/platform/PlatformServices.h index 72a22bbce..291f77d99 100644 --- a/targets/platform/PlatformServices.h +++ b/targets/platform/PlatformServices.h @@ -1,5 +1,6 @@ #pragma once +#include "IPlatformFileIO.h" #include "IPlatformInput.h" #include "IPlatformLeaderboard.h" #include "IPlatformNetwork.h" @@ -11,6 +12,7 @@ // instead of concrete globals directly. Bindings are established // by the app layer at startup. +extern IPlatformFileIO& PlatformFileIO; extern IPlatformInput& PlatformInput; extern IPlatformProfile& PlatformProfile; extern IPlatformRenderer& PlatformRender; diff --git a/targets/platform/StdFileIO.h b/targets/platform/StdFileIO.h new file mode 100644 index 000000000..d5bf0c5fa --- /dev/null +++ b/targets/platform/StdFileIO.h @@ -0,0 +1,92 @@ +#pragma once + +#include "IPlatformFileIO.h" + +#include +#include +#include + +#if defined(__linux__) +#include +#endif + +// Standard filesystem implementation for desktop platforms. +class StdFileIO : public IPlatformFileIO { +public: + ReadResult readFile(const std::filesystem::path& path, void* buffer, + std::size_t capacity) override { + std::error_code ec; + auto size = std::filesystem::file_size(path, ec); + if (ec) return {ReadStatus::NotFound, 0, 0}; + if (size > capacity) return {ReadStatus::TooLarge, 0, static_cast(size)}; + + std::ifstream f(path, std::ios::binary); + if (!f) return {ReadStatus::NotFound, 0, 0}; + f.read(static_cast(buffer), static_cast(size)); + auto read = static_cast(f.gcount()); + return {f ? ReadStatus::Ok : ReadStatus::ReadError, read, static_cast(size)}; + } + + ReadResult readFileSegment(const std::filesystem::path& path, + std::size_t offset, void* buffer, + std::size_t bytesToRead) override { + std::error_code ec; + auto size = std::filesystem::file_size(path, ec); + if (ec) return {ReadStatus::NotFound, 0, 0}; + if (offset + bytesToRead > size) return {ReadStatus::TooLarge, 0, static_cast(size)}; + + std::ifstream f(path, std::ios::binary); + if (!f) return {ReadStatus::NotFound, 0, 0}; + f.seekg(static_cast(offset)); + f.read(static_cast(buffer), static_cast(bytesToRead)); + auto read = static_cast(f.gcount()); + return {f ? ReadStatus::Ok : ReadStatus::ReadError, read, static_cast(size)}; + } + + std::vector readFileToVec( + const std::filesystem::path& path) override { + std::error_code ec; + auto size = std::filesystem::file_size(path, ec); + if (ec) return {}; + + std::vector data(static_cast(size)); + std::ifstream f(path, std::ios::binary); + if (!f) return {}; + f.read(reinterpret_cast(data.data()), static_cast(size)); + return data; + } + + bool writeFile(const std::filesystem::path& path, const void* buffer, + std::size_t bytesToWrite) override { + std::ofstream f(path, std::ios::binary); + if (!f) return false; + f.write(static_cast(buffer), static_cast(bytesToWrite)); + return f.good(); + } + + bool exists(const std::filesystem::path& path) override { + return std::filesystem::exists(path); + } + + std::size_t fileSize(const std::filesystem::path& path) override { + std::error_code ec; + auto size = std::filesystem::file_size(path, ec); + return ec ? 0 : static_cast(size); + } + + std::filesystem::path getBasePath() override { +#if defined(__linux__) + char buf[4096]; + ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); + if (len > 0) { + buf[len] = '\0'; + return std::filesystem::path(buf).parent_path(); + } +#endif + return std::filesystem::current_path(); + } + + std::filesystem::path getUserDataPath() override { + return getBasePath(); + } +};