From e1a66b0ad0183b6319755b20e61bc4cc731cd3e7 Mon Sep 17 00:00:00 2001 From: notmatthewbeshay <92357869+NotMachow@users.noreply.github.com> Date: Mon, 9 Mar 2026 23:26:18 +1100 Subject: [PATCH] Modernise portable file and timing utilities --- Minecraft.Client/Utils/ArchiveFile.cpp | 69 +------ Minecraft.World/IO/Files/File.cpp | 191 ++++++++++++++---- Minecraft.World/Level/CustomLevelSource.cpp | 84 +++----- Minecraft.World/Util/PerformanceTimer.cpp | 22 +- Minecraft.World/Util/PerformanceTimer.h | 17 +- Minecraft.World/Util/PortableFileIO.h | 90 +++++++++ .../WorldGen/Layers/BiomeOverrideLayer.cpp | 47 ++--- 7 files changed, 303 insertions(+), 217 deletions(-) create mode 100644 Minecraft.World/Util/PortableFileIO.h diff --git a/Minecraft.Client/Utils/ArchiveFile.cpp b/Minecraft.Client/Utils/ArchiveFile.cpp index b2a8b383b..8c2754fc4 100644 --- a/Minecraft.Client/Utils/ArchiveFile.cpp +++ b/Minecraft.Client/Utils/ArchiveFile.cpp @@ -1,6 +1,7 @@ #include "../Platform/stdafx.h" #include "../../Minecraft.World/Util/StringHelpers.h" +#include "../../Minecraft.World/Util/PortableFileIO.h" #include "../../Minecraft.World/IO/Streams/Compression.h" #include "ArchiveFile.h" @@ -120,66 +121,18 @@ byteArray ArchiveFile::getFile(const std::wstring &filename) memcpy( out.data, m_cachedData + data->ptr, data->filesize ); #else + const unsigned int fileSize = static_cast(data->filesize); + PBYTE pbData = new BYTE[fileSize == 0 ? 1 : fileSize]; + out = byteArray(pbData, fileSize); + const PortableFileIO::BinaryReadResult readResult = PortableFileIO::ReadBinaryFileSegment( + m_sourcefile.getPath(), + static_cast(data->ptr), + out.data, + static_cast(data->filesize)); -#if defined(_UNICODE) && !defined(__linux__) - HANDLE hfile = CreateFile( m_sourcefile.getPath().c_str(), - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); -#else - app.DebugPrintf("Createfile archive\n"); - HANDLE hfile = CreateFile( wstringtofilename(m_sourcefile.getPath()), - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL - ); -#endif - - if (hfile != INVALID_HANDLE_VALUE) + if (readResult.status != PortableFileIO::BinaryReadStatus::ok) { - app.DebugPrintf("hfile ok\n"); - DWORD ok = SetFilePointer( hfile, - data->ptr, - NULL, - FILE_BEGIN - ); - - if (ok != INVALID_SET_FILE_POINTER) - { - PBYTE pbData = new BYTE[ data->filesize ]; - - DWORD bytesRead = -1; - BOOL bSuccess = ReadFile( hfile, - (LPVOID) pbData, - data->filesize, - &bytesRead, - NULL - ); - - if(bSuccess==FALSE) - { - app.FatalLoadError(); - } - assert(bytesRead == data->filesize); - out = byteArray(pbData, data->filesize); - } - else - { - app.FatalLoadError(); - } - - CloseHandle(hfile); - } - else - { - app.DebugPrintf("bad hfile\n"); + app.DebugPrintf("Failed to read archive file segment\n"); app.FatalLoadError(); } #endif diff --git a/Minecraft.World/IO/Files/File.cpp b/Minecraft.World/IO/Files/File.cpp index e2326d25e..aa789546a 100644 --- a/Minecraft.World/IO/Files/File.cpp +++ b/Minecraft.World/IO/Files/File.cpp @@ -3,6 +3,11 @@ #include "../../Level/Storage/McRegionLevelStorageSource.h" #include "File.h" +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) +#include +#include +#endif + #ifdef __PS3__ #include #endif @@ -17,6 +22,34 @@ const std::wstring File::pathRoot = L"GAME:"; // Path root after pathSeparator h const std::wstring File::pathRoot = L""; // Path root after pathSeparator has been removed #endif +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) +namespace +{ + namespace fs = std::filesystem; + + fs::path ToFilesystemPath(const std::wstring& path) + { + const std::string nativePath = wstringtofilename(path); + return fs::u8path(nativePath); + } + + std::wstring ToFilename(const fs::path& path) + { + const std::string filename = path.filename().u8string(); + return filenametowstring(filename.c_str()); + } + + __int64 ToEpochMilliseconds(const fs::file_time_type& fileTime) + { + using namespace std::chrono; + + const auto systemTime = time_point_cast( + fileTime - fs::file_time_type::clock::now() + system_clock::now()); + return static_cast<__int64>(systemTime.time_since_epoch().count()); + } +} +#endif + //Creates a new File instance from a parent abstract pathname and a child pathname string. File::File( const File &parent, const std::wstring& child ) { @@ -97,7 +130,36 @@ this->parent = NULL; //true if and only if the file or directory is successfully deleted; false otherwise bool File::_delete() { +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + const bool result = fs::remove(ToFilesystemPath(getPath()), error); #if defined _UNICODE + if( !result || error ) + { +#ifndef _CONTENT_PACKAGE + printf( "File::_delete - Error code %d (%#0.8X)\n", error.value(), error.value() ); +#endif + return false; + } + return true; +#elif defined(__linux__) + if( !result || error ) + { + printf("Unable to delete file :("); + return false; + } + return true; +#else + if( !result || error ) + { +#ifndef _CONTENT_PACKAGE + printf( "File::_delete - Error code %d (%#0.8X)\n", error.value(), error.value() ); +#endif + return false; + } + return true; +#endif +#elif defined _UNICODE BOOL result = DeleteFile( getPath().c_str() ); #elif defined(__linux__) // FIXME @@ -126,7 +188,10 @@ bool File::_delete() //true if and only if the directory was created; false otherwise bool File::mkdir() const { -#if defined (_UNICODE) +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + return fs::create_directory(ToFilesystemPath(getPath()), error); +#elif defined (_UNICODE) return CreateDirectory( getPath().c_str(), NULL) != 0; #elif defined(__linux__) return ::mkdir(wstringtofilename(getPath()), 0777) == 0; @@ -157,6 +222,22 @@ bool File::mkdir() const // bool File::mkdirs() const { +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + const fs::path path = ToFilesystemPath(getPath()); + + if( fs::exists(path, error) ) + { + return fs::is_directory(path, error); + } + + if( error ) + { + return false; + } + + return fs::create_directories(path, error); +#else std::vector path = stringSplit( m_abstractPathName, pathSeparator ); std::wstring pathToHere = L""; @@ -208,6 +289,7 @@ bool File::mkdirs() const assert( exists() ); return true; +#endif } /* @@ -223,7 +305,10 @@ return (File *) parent; bool File::exists() const { // TODO 4J Stu - Possible we could get an error result from something other than the file not existing? -#if defined(_UNICODE) +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + return fs::exists(ToFilesystemPath(getPath()), error); +#elif defined(_UNICODE) return GetFileAttributes( getPath().c_str() ) != -1; #elif defined(__linux__) // BAD DOBBY BAD DOBBY @@ -252,6 +337,16 @@ bool File::isFile() const //true if and only if the renaming succeeded; false otherwise bool File::renameTo(File dest) { +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + fs::rename(ToFilesystemPath(getPath()), ToFilesystemPath(dest.getPath()), error); + if(error) + { + perror("File::renameTo - Error renaming file"); + return false; + } + return true; +#else std::string sourcePath = wstringtofilename(getPath()); std::string destPath = wstringtofilename(dest.getPath()); @@ -266,37 +361,9 @@ bool File::renameTo(File dest) { return true; } +#endif } -#if defined(__linux__) -// DecalOverdose: Stolen from my other project -void listFiles(const char *directory) { - DIR *dp; - struct dirent *entry; - struct stat fileStat; - - dp = opendir(directory); - if (dp == NULL) { - perror("opendir"); - return; - } - - while ((entry = readdir(dp)) != NULL) { - char fullPath[1024]; - snprintf(fullPath, sizeof(fullPath), "%s/%s", directory, entry->d_name); - - if (stat(fullPath, &fileStat) == 0) { - if (S_ISREG(fileStat.st_mode)) { - printf("File: %s\n", entry->d_name); - } - } else { - perror("stat"); - } - } - closedir(dp); -} -#endif // __linux__ - //Returns an array of abstract pathnames denoting the files in the directory denoted by this abstract pathname. //If this abstract pathname does not denote a directory, then this method returns null. Otherwise an array of File objects is returned, //one for each file or directory in the directory. Pathnames denoting the directory itself and the directory's parent directory @@ -319,6 +386,13 @@ std::vector *File::listFiles() const if( !isDirectory() ) return vOutput; +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + for( fs::directory_iterator it(ToFilesystemPath(getPath()), error); !error && it != fs::directory_iterator(); it.increment(error) ) + { + vOutput->push_back( new File( *this, ToFilename(it->path()) ) ); + } +#else #ifdef __PS3__ const char *lpFileName=wstringtofilename(getPath()); char filePath[256]; @@ -447,6 +521,7 @@ std::vector *File::listFiles() const FindClose( hFind); } #endif +#endif #endif return vOutput; } @@ -469,6 +544,17 @@ std::vector *File::listFiles(FileFilter *filter) const std::vector *vOutput = new std::vector(); +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + for( fs::directory_iterator it(ToFilesystemPath(getPath()), error); !error && it != fs::directory_iterator(); it.increment(error) ) + { + File thisFile = File( *this, ToFilename(it->path()) ); + if( filter->accept( &thisFile ) ) + { + vOutput->push_back( new File( thisFile ) ); + } + } +#else #ifdef __PS3__ const char *lpFileName=wstringtofilename(getPath()); char filePath[256]; @@ -551,6 +637,7 @@ std::vector *File::listFiles(FileFilter *filter) const FindClose( hFind); } #endif +#endif #endif return vOutput; } @@ -560,7 +647,10 @@ std::vector *File::listFiles(FileFilter *filter) const //true if and only if the file denoted by this abstract pathname exists and is a directory; false otherwise bool File::isDirectory() const { -#if defined(_UNICODE) +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + return fs::is_directory(ToFilesystemPath(getPath()), error); +#elif defined(_UNICODE) return exists() && ( GetFileAttributes( getPath().c_str() ) & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY; #elif defined(__linux__) const char *dirpath = wstringtofilename(getPath()); @@ -639,17 +729,20 @@ __int64 File::length() return 0; } return statData.fileSize; -#elif defined(__linux__) - struct stat fileInfoBuffer; - const char *path = wstringtofilename(getPath()); +#elif !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + const fs::path path = ToFilesystemPath(getPath()); - int result = stat(path, &fileInfoBuffer); - - if(result == 0) { - return fileInfoBuffer.st_size; - } else { - return 0; + if( fs::is_regular_file(path, error) ) + { + const auto size = fs::file_size(path, error); + if( !error ) + { + return static_cast<__int64>(size); + } } + + return 0; #else WIN32_FILE_ATTRIBUTE_DATA fileInfoBuffer; #ifdef _UNICODE @@ -689,7 +782,21 @@ __int64 File::length() //or 0L if the file does not exist or if an I/O error occurs __int64 File::lastModified() { -#if !defined(__linux__) +#if !defined(__PS3__) && !defined(__ORBIS__) && !defined(__PSVITA__) + std::error_code error; + const fs::path path = ToFilesystemPath(getPath()); + + if( fs::is_regular_file(path, error) ) + { + const fs::file_time_type lastWriteTime = fs::last_write_time(path, error); + if( !error ) + { + return ToEpochMilliseconds(lastWriteTime); + } + } + + return 0l; +#elif !defined(__linux__) WIN32_FILE_ATTRIBUTE_DATA fileInfoBuffer; #ifdef _UNICODE BOOL result = GetFileAttributesEx( diff --git a/Minecraft.World/Level/CustomLevelSource.cpp b/Minecraft.World/Level/CustomLevelSource.cpp index 5753d6092..d31aed6b2 100644 --- a/Minecraft.World/Level/CustomLevelSource.cpp +++ b/Minecraft.World/Level/CustomLevelSource.cpp @@ -1,4 +1,5 @@ #include "../Platform/stdafx.h" +#include "../Util/PortableFileIO.h" #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.level.biome.h" #include "../Headers/net.minecraft.world.level.levelgen.h" @@ -19,86 +20,47 @@ CustomLevelSource::CustomLevelSource(Level *level, __int64 seed, bool generateSt m_heightmapOverride = byteArray( (m_XZSize*16) * (m_XZSize*16) ); -#ifdef _UNICODE - std::wstring path = L"GAME:\\GameRules\\heightmap.bin"; - -#else #ifdef _WINDOWS64 - std::string path = "GameRules\\heightmap.bin"; + const std::wstring path = L"GameRules\\heightmap.bin"; #else - std::string path = "GAME:\\GameRules\\heightmap.bin"; + const std::wstring path = L"GAME:\\GameRules\\heightmap.bin"; #endif -#endif - HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if( file == INVALID_HANDLE_VALUE ) + const PortableFileIO::BinaryReadResult heightmapReadResult = PortableFileIO::ReadBinaryFile(path, m_heightmapOverride.data, m_heightmapOverride.length); + if(heightmapReadResult.status == PortableFileIO::BinaryReadStatus::not_found) { app.FatalLoadError(); - DWORD error = GetLastError(); assert(false); } - else + else if(heightmapReadResult.status == PortableFileIO::BinaryReadStatus::too_large) { - -#ifdef _DURANGO - __debugbreak(); // TODO - DWORD bytesRead,dwFileSize = 0; -#else - DWORD bytesRead,dwFileSize = GetFileSize(file,NULL); -#endif - if(dwFileSize > m_heightmapOverride.length) - { - app.DebugPrintf("Heightmap binary is too large!!\n"); - __debugbreak(); - } - BOOL bSuccess = ReadFile(file,m_heightmapOverride.data,dwFileSize,&bytesRead,NULL); - - if(bSuccess==FALSE) - { - app.FatalLoadError(); - } - CloseHandle(file); + app.DebugPrintf("Heightmap binary is too large!!\n"); + __debugbreak(); + } + else if(heightmapReadResult.status != PortableFileIO::BinaryReadStatus::ok) + { + app.FatalLoadError(); } m_waterheightOverride = byteArray( (m_XZSize*16) * (m_XZSize*16) ); -#ifdef _UNICODE - std::wstring waterHeightPath = L"GAME:\\GameRules\\waterheight.bin"; - -#else #ifdef _WINDOWS64 - std::string waterHeightPath = "GameRules\\waterheight.bin"; + const std::wstring waterHeightPath = L"GameRules\\waterheight.bin"; #else - std::string waterHeightPath = "GAME:\\GameRules\\waterheight.bin"; + const std::wstring waterHeightPath = L"GAME:\\GameRules\\waterheight.bin"; #endif -#endif - file = CreateFile(waterHeightPath.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if( file == INVALID_HANDLE_VALUE ) + const PortableFileIO::BinaryReadResult waterHeightReadResult = PortableFileIO::ReadBinaryFile(waterHeightPath, m_waterheightOverride.data, m_waterheightOverride.length); + if(waterHeightReadResult.status == PortableFileIO::BinaryReadStatus::not_found) { - DWORD error = GetLastError(); - //assert(false); memset(m_waterheightOverride.data, level->seaLevel, m_waterheightOverride.length); } - else + else if(waterHeightReadResult.status == PortableFileIO::BinaryReadStatus::too_large) { - -#ifdef _DURANGO - __debugbreak(); // TODO - DWORD bytesRead,dwFileSize = 0; -#else - DWORD bytesRead,dwFileSize = GetFileSize(file,NULL); -#endif - if(dwFileSize > m_waterheightOverride.length) - { - app.DebugPrintf("waterheight binary is too large!!\n"); - __debugbreak(); - } - BOOL bSuccess = ReadFile(file,m_waterheightOverride.data,dwFileSize,&bytesRead,NULL); - - if(bSuccess==FALSE) - { - app.FatalLoadError(); - } - CloseHandle(file); + app.DebugPrintf("waterheight binary is too large!!\n"); + __debugbreak(); + } + else if(waterHeightReadResult.status != PortableFileIO::BinaryReadStatus::ok) + { + app.FatalLoadError(); } caveFeature = new LargeCaveFeature(); diff --git a/Minecraft.World/Util/PerformanceTimer.cpp b/Minecraft.World/Util/PerformanceTimer.cpp index 96ce372ef..42b00a2a7 100644 --- a/Minecraft.World/Util/PerformanceTimer.cpp +++ b/Minecraft.World/Util/PerformanceTimer.cpp @@ -3,33 +3,17 @@ PerformanceTimer::PerformanceTimer() { -#if !defined (__linux__) - // Get the frequency of the timer - LARGE_INTEGER qwTicksPerSec; - QueryPerformanceFrequency( &qwTicksPerSec ); - m_fSecsPerTick = 1.0f / (float)qwTicksPerSec.QuadPart; - Reset(); -#endif } void PerformanceTimer::Reset() { -#if !defined (__linux__) - QueryPerformanceCounter( &m_qwStartTime ); -#endif + m_startTime = std::chrono::steady_clock::now(); } void PerformanceTimer::PrintElapsedTime(const std::wstring &description) { -#if !defined (__linux__) - LARGE_INTEGER qwNewTime, qwDeltaTime; + const std::chrono::duration elapsedTime = std::chrono::steady_clock::now() - m_startTime; - QueryPerformanceCounter( &qwNewTime ); - - qwDeltaTime.QuadPart = qwNewTime.QuadPart - m_qwStartTime.QuadPart; - float fElapsedTime = m_fSecsPerTick * ((FLOAT)(qwDeltaTime.QuadPart)); - - app.DebugPrintf("TIMER: %ls: Elapsed time %f\n", description.c_str(), fElapsedTime); -#endif + app.DebugPrintf("TIMER: %ls: Elapsed time %f\n", description.c_str(), elapsedTime.count()); } diff --git a/Minecraft.World/Util/PerformanceTimer.h b/Minecraft.World/Util/PerformanceTimer.h index 5ceaa2480..7fca90507 100644 --- a/Minecraft.World/Util/PerformanceTimer.h +++ b/Minecraft.World/Util/PerformanceTimer.h @@ -1,13 +1,24 @@ #pragma once +#ifdef __valid +#pragma push_macro("__valid") +#undef __valid +#define PERFORMANCE_TIMER_RESTORE_VALID_MACRO +#endif +#include +#ifdef PERFORMANCE_TIMER_RESTORE_VALID_MACRO +#pragma pop_macro("__valid") +#undef PERFORMANCE_TIMER_RESTORE_VALID_MACRO +#endif +#include + class PerformanceTimer { private: - LARGE_INTEGER m_qwStartTime; - float m_fSecsPerTick; + std::chrono::steady_clock::time_point m_startTime; public: PerformanceTimer(); void Reset(); void PrintElapsedTime(const std::wstring &description); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Util/PortableFileIO.h b/Minecraft.World/Util/PortableFileIO.h new file mode 100644 index 000000000..e3e70a4ac --- /dev/null +++ b/Minecraft.World/Util/PortableFileIO.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include + +#include "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 BinaryReadResult ReadBinaryFile(const std::wstring &path, void *buffer, std::size_t capacity) + { + const std::string nativePath = wstringtofilename(path); + std::ifstream stream(nativePath.c_str(), std::ios::binary | std::ios::ate); + if (!stream.is_open()) + { + return { BinaryReadStatus::not_found, 0, 0 }; + } + + const std::streamoff endPosition = stream.tellg(); + if (endPosition < 0) + { + return { BinaryReadStatus::read_error, 0, 0 }; + } + + const std::size_t fileSize = static_cast(endPosition); + if (fileSize > capacity) + { + return { BinaryReadStatus::too_large, 0, fileSize }; + } + + stream.seekg(0, std::ios::beg); + stream.read(reinterpret_cast(buffer), static_cast(fileSize)); + const std::size_t bytesRead = static_cast(stream.gcount()); + if ((!stream && !stream.eof()) || 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) + { + const std::string nativePath = wstringtofilename(path); + std::ifstream stream(nativePath.c_str(), std::ios::binary | std::ios::ate); + if (!stream.is_open()) + { + return { BinaryReadStatus::not_found, 0, 0 }; + } + + const std::streamoff endPosition = stream.tellg(); + if (endPosition < 0) + { + return { BinaryReadStatus::read_error, 0, 0 }; + } + + const std::size_t fileSize = static_cast(endPosition); + if ((offset > fileSize) || (bytesToRead > (fileSize - offset))) + { + return { BinaryReadStatus::too_large, 0, fileSize }; + } + + stream.seekg(static_cast(offset), std::ios::beg); + stream.read(reinterpret_cast(buffer), static_cast(bytesToRead)); + const std::size_t bytesRead = static_cast(stream.gcount()); + if ((!stream && !stream.eof()) || bytesRead != bytesToRead) + { + return { BinaryReadStatus::read_error, bytesRead, fileSize }; + } + + return { BinaryReadStatus::ok, bytesRead, fileSize }; + } +} diff --git a/Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp b/Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp index 436cdc5ae..9f6c90585 100644 --- a/Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp +++ b/Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp @@ -1,4 +1,5 @@ #include "../../Platform/stdafx.h" +#include "../../Util/PortableFileIO.h" #include "../../Headers/net.minecraft.world.level.biome.h" #include "../../Headers/net.minecraft.world.level.newbiome.layer.h" #include "../../Headers/net.minecraft.world.level.h" @@ -9,47 +10,25 @@ BiomeOverrideLayer::BiomeOverrideLayer(int seedMixup) : Layer(seedMixup) { m_biomeOverride = byteArray( width * height ); -#ifdef _UNICODE - std::wstring path = L"GAME:\\GameRules\\biomemap.bin"; - HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -#else #ifdef _WINDOWS64 - std::string path = "GameRules\\biomemap.bin"; + const std::wstring path = L"GameRules\\biomemap.bin"; #else - std::string path = "GAME:\\GameRules\\biomemap.bin"; + const std::wstring path = L"GAME:\\GameRules\\biomemap.bin"; #endif - HANDLE file = CreateFile(path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -#endif - if( file == INVALID_HANDLE_VALUE ) + const PortableFileIO::BinaryReadResult readResult = PortableFileIO::ReadBinaryFile(path, m_biomeOverride.data, m_biomeOverride.length); + if(readResult.status == PortableFileIO::BinaryReadStatus::not_found) { - DWORD error = GetLastError(); - //assert(false); app.DebugPrintf("Biome override not found, using plains as default\n"); - memset(m_biomeOverride.data,Biome::plains->id,m_biomeOverride.length); } - else + else if(readResult.status == PortableFileIO::BinaryReadStatus::too_large) { - -#ifdef _DURANGO - __debugbreak(); // TODO - DWORD bytesRead,dwFileSize = 0; -#else - DWORD bytesRead,dwFileSize = GetFileSize(file,NULL); -#endif - if(dwFileSize > m_biomeOverride.length) - { - app.DebugPrintf("Biomemap binary is too large!!\n"); - __debugbreak(); - } - BOOL bSuccess = ReadFile(file,m_biomeOverride.data,dwFileSize,&bytesRead,NULL); - - if(bSuccess==FALSE) - { - app.FatalLoadError(); - } - - CloseHandle(file); + app.DebugPrintf("Biomemap binary is too large!!\n"); + __debugbreak(); + } + else if(readResult.status != PortableFileIO::BinaryReadStatus::ok) + { + app.FatalLoadError(); } } @@ -78,4 +57,4 @@ intArray BiomeOverrideLayer::getArea(int xo, int yo, int w, int h) } } return result; -} \ No newline at end of file +}