diff --git a/CMakeLists.txt b/CMakeLists.txt index bf6e5ecb..487e3de0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required (VERSION 3.18) +cmake_policy(SET CMP0091 NEW) ## Project Definition and Options ## diff --git a/src/srv/CMakeLists.txt b/src/srv/CMakeLists.txt index 999a4e78..cf0a5d46 100644 --- a/src/srv/CMakeLists.txt +++ b/src/srv/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required (VERSION 3.18) ## Project Definition and Options ## @@ -53,3 +53,23 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" AND CMAKE_BUILD_TYPE MATCHES "Release") COMPILE_PDB_OUTPUT_DIR ${CMAKE_BINARY_DIR} ) endif() + +# Use static CRT (the code is memcpy-heavy, avoid calling those dlls if we have to) +set(CompilerFlags + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + ) +foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + string(REPLACE "-MD" "-MT" ${CompilerFlag} "${${CompilerFlag}}") +endforeach() + +if (CMAKE_BUILD_TYPE MATCHES "Debug") + set_property(TARGET EGL3_SRV PROPERTY MSVC_RUNTIME_LIBRARY MultiThreadedDebug) +else() + set_property(TARGET EGL3_SRV PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded) +endif() \ No newline at end of file diff --git a/src/srv/MountedArchive.cpp b/src/srv/MountedArchive.cpp index f4f6a331..d20a7b77 100644 --- a/src/srv/MountedArchive.cpp +++ b/src/srv/MountedArchive.cpp @@ -6,36 +6,54 @@ namespace EGL3::Service { using namespace Storage; - std::vector GetMountFiles(const Game::ArchiveList& Files) + MountedArchive::MountedArchive(const std::filesystem::path& Path, Game::Archive&& Archive) : + Archive(std::move(Archive)), + ArchiveLists(this->Archive), + LUT(ArchiveLists), + Disk(GetMountedFiles(), Utils::Random(), HandleCluster), + DriveLetter(0) { - std::vector MountedFiles; - MountedFiles.reserve(Files.size()); + Disk.Initialize(); - int Idx = 0; - for (auto& File : Files) { - MountedFiles.push_back({ - .Path = File.Filename, - .FileSize = File.FileSize, - .UserContext = (void*)Idx++ - }); + Disk.Create(); + + Disk.Mount(); + } + + MountedArchive::~MountedArchive() + { + } + + char MountedArchive::GetDriveLetter() const + { + if (!DriveLetter) { + DriveLetter = Disk.GetDriveLetter(); } + return DriveLetter; + } - return MountedFiles; + std::filesystem::path MountedArchive::GetArchivePath() const + { + return Archive.GetPath(); } - MountedArchive::MountedArchive(const std::filesystem::path& Path, Storage::Game::Archive&& Archive) : - DriveLetter(0), - Archive(std::move(Archive)), - ArchiveLists(this->Archive), - Disk(GetMountFiles(ArchiveLists.Files), Utils::Random()) + MountedArchive::Stats MountedArchive::QueryStats() const { - Disk.HandleFileCluster.Set([this](void* Ctx, uint64_t LCN, uint8_t Buffer[4096]) { HandleFileCluster(Ctx, LCN, Buffer); }); + if (!Counter.IsValid()) { + Counter = DriveCounter(GetDriveLetter()); + } + if (Counter.IsValid()) { + return Counter.GetData(); + } + return Stats{}; + } - Disk.Initialize(); + MountedArchive::SectionLUT::SectionLUT(const Lists& ArchiveLists) + { + LUT.reserve(ArchiveLists.Files.size()); - SectionLUT.reserve(ArchiveLists.Files.size()); for (auto& File : ArchiveLists.Files) { - auto& Sections = SectionLUT.emplace_back(); + auto& Sections = LUT.emplace_back(); uint32_t ClusterCount = Utils::Align<4096>(File.FileSize) / 4096; Sections.reserve(ClusterCount); @@ -50,7 +68,7 @@ namespace EGL3::Service { for (uint32_t i = 0; i < ClusterCount; ++i) { uint32_t BytesToSelect = std::min(4096llu, File.FileSize - i * 4096llu); - Sections.emplace_back(SectionParts.size()); + Sections.emplace_back(Parts.size()); do { if (ItrDataOffset == Itr->Size) { ++Itr; @@ -58,7 +76,7 @@ namespace EGL3::Service { } auto& ChunkPart = *Itr; auto SectionPartSize = std::min(ChunkPart.Size - ItrDataOffset, BytesToSelect); - SectionParts.emplace_back( + Parts.emplace_back( GetDataItr(ChunkPart.ChunkIdx) + ChunkPart.Offset + ItrDataOffset, SectionPartSize ); @@ -66,54 +84,43 @@ namespace EGL3::Service { ItrDataOffset += SectionPartSize; EGL3_VERIFY(ItrDataOffset <= Itr->Size, "Invalid data offset"); } while (BytesToSelect); - SectionParts.emplace_back(); + Parts.emplace_back(); } - } - - Disk.Create(); - Disk.Mount(); + Contexts.emplace_back(Sections, Parts, ArchiveLists.ChunkDatas.begin()); + } } - MountedArchive::~MountedArchive() + MountedArchive::SectionContext::SectionContext(const std::vector& const LUT, const std::vector& const Parts, const Storage::Game::ArchiveListIteratorReadonly DataBegin) : + LUT(LUT), + Parts(Parts), + DataBegin(DataBegin) { - } - char MountedArchive::GetDriveLetter() const - { - if (!DriveLetter) { - DriveLetter = Disk.GetDriveLetter(); - } - return DriveLetter; } - std::filesystem::path MountedArchive::GetArchivePath() const + std::vector MountedArchive::GetMountedFiles() { - return Archive.GetPath(); - } + std::vector MountedFiles; + MountedFiles.reserve(ArchiveLists.Files.size()); - MountedArchive::Stats MountedArchive::QueryStats() const - { - if (!Counter.IsValid()) { - Counter = DriveCounter(GetDriveLetter()); - } - if (Counter.IsValid()) { - return Counter.GetData(); + size_t Idx = 0; + for (auto& File : ArchiveLists.Files) { + MountedFiles.push_back({ + .Path = File.Filename, + .FileSize = File.FileSize, + .UserContext = (void*)&LUT.Contexts[Idx++] + }); } - return Stats{}; - } - void MountedArchive::HandleFileCluster(void* Ctx, uint64_t LCN, uint8_t Buffer[4096]) const noexcept - { - auto& File = SectionLUT[(size_t)Ctx]; + return MountedFiles; + } - if (File.size() < LCN) [[unlikely]] { - ZeroMemory(Buffer, 4096); - return; - } + void MountedArchive::HandleCluster(void* CtxPtr, uint64_t LCN, uint8_t Buffer[4096]) noexcept { + auto& Ctx = *(MountedArchive::SectionContext*)CtxPtr; - for(auto Itr = SectionParts.begin() + File[LCN]; Itr->IsValid(); ++Itr) { - auto Ptr = ArchiveLists.ChunkDatas.begin() + Itr->GetPtr(); + for (auto Itr = Ctx.Parts.begin() + Ctx.LUT[LCN]; Itr->IsValid(); ++Itr) { + auto Ptr = Ctx.DataBegin + Itr->GetPtr(); Ptr.FastCopy((char*)Buffer, Itr->GetSize()); Buffer = (uint8_t*)Buffer + Itr->GetSize(); } diff --git a/src/srv/MountedArchive.h b/src/srv/MountedArchive.h index 130ab4c8..eb6ff2ac 100644 --- a/src/srv/MountedArchive.h +++ b/src/srv/MountedArchive.h @@ -20,15 +20,13 @@ namespace EGL3::Service { Stats QueryStats() const; private: - void HandleFileCluster(void* Ctx, uint64_t LCN, uint8_t Buffer[4096]) const noexcept; - struct Lists { const Storage::Game::ArchiveList Files; const Storage::Game::ArchiveList ChunkParts; const Storage::Game::ArchiveList ChunkInfos; const Storage::Game::ArchiveList ChunkDatas; - Lists(Storage::Game::Archive& Archive) : + Lists(const Storage::Game::Archive& Archive) : Files(Archive), ChunkParts(Archive), ChunkInfos(Archive), @@ -41,39 +39,60 @@ namespace EGL3::Service { struct SectionPart { uint64_t Data; - SectionPart() : + SectionPart() noexcept : Data(0) { } - SectionPart(uint64_t Ptr, uint16_t Size) : + SectionPart(uint64_t Ptr, uint16_t Size) noexcept : Data(uint64_t(Size) << 48 | Ptr) { } - bool IsValid() const + bool IsValid() const noexcept { return Data; } - uint64_t GetPtr() const + uint64_t GetPtr() const noexcept { return Data & (1llu << 48) - 1; } - uint16_t GetSize() const + uint16_t GetSize() const noexcept { return Data >> 48; } }; - Storage::Game::Archive Archive; - Lists ArchiveLists; + struct SectionLUT; + + struct SectionContext { + const std::vector& const LUT; + const std::vector& const Parts; + const Storage::Game::ArchiveListIteratorReadonly DataBegin; + + SectionContext(const std::vector& const LUT, const std::vector& const Parts, const Storage::Game::ArchiveListIteratorReadonly DataBegin); + }; + + struct SectionLUT { + std::vector Parts; + std::vector> LUT; + std::vector Contexts; + + SectionLUT(const Lists& ArchiveLists); + }; + + std::vector GetMountedFiles(); + + static void HandleCluster(void* CtxPtr, uint64_t LCN, uint8_t Buffer[4096]) noexcept; + + const Storage::Game::Archive Archive; + const Lists ArchiveLists; + const SectionLUT LUT; MountedDisk Disk; - std::vector SectionParts; - std::vector> SectionLUT; mutable DriveCounter Counter; mutable char DriveLetter; }; diff --git a/src/srv/MountedDisk.cpp b/src/srv/MountedDisk.cpp index 72744b61..002baebd 100644 --- a/src/srv/MountedDisk.cpp +++ b/src/srv/MountedDisk.cpp @@ -18,28 +18,27 @@ namespace EGL3::Service { static constexpr uint32_t SectorsPerMegabyte = (1 << 20) / 4096; - // I use sector and cluster somewhat interchangably, even though technically - // a sector would be 512 bytes and a cluster 4096 bytes, thanks wikipedia + // I use sector and cluster somewhat interchangably, both a cluster + // and a sector would be 4096 bytes in this instance, thanks wikipedia // Sorry not sorry, I'll fix that eventually, I guess struct MountedData { uint8_t MBRData[4096]; - uint8_t BlankData[4096]; uint32_t DiskSignature; std::vector Files; AppendingFile* Disk; SPD_STORAGE_UNIT* Unit; SPD_GUARD CloseGuard; - const decltype(MountedDisk::HandleFileCluster)& FileClusterCallback; + MountedDisk::ClusterCallback FileClusterCallback; XorFilter DiskFilter; - MountedData(const decltype(MountedDisk::HandleFileCluster)& Callback) : + MountedData() : MBRData{}, - BlankData{}, DiskSignature(), Disk(nullptr), Unit(nullptr), CloseGuard(SPD_GUARD_INIT), - FileClusterCallback(Callback) + FileClusterCallback(nullptr), + DiskFilter() { } @@ -47,18 +46,11 @@ namespace EGL3::Service { static std::allocator DataAllocator; - MountedDisk::MountedDisk(const std::vector& Files, uint32_t DiskSignature) : - HandleFileCluster([](void* Ctx, uint64_t LCN, uint8_t Buffer[4096]) { - memset(Buffer, 'A', 1024); - memset(Buffer + 1024, 'B', 1024); - memset(Buffer + 2048, 'C', 1024); - memset(Buffer + 3072, 'D', 1024); - *(uint64_t*)Buffer = LCN; - }), + MountedDisk::MountedDisk(const std::vector& Files, uint32_t DiskSignature, ClusterCallback Callback) : PrivateData(DataAllocator.allocate(1)) { auto Data = (MountedData*)PrivateData; - std::construct_at(Data, HandleFileCluster); + std::construct_at(Data); Data->Files.reserve(Files.size()); for (auto& File : Files) { @@ -74,6 +66,7 @@ namespace EGL3::Service { } Data->DiskSignature = DiskSignature; + Data->FileClusterCallback = Callback; } MountedDisk::~MountedDisk() @@ -158,16 +151,16 @@ namespace EGL3::Service { EGL3_VERIFY(Data->DiskFilter.Initialize(DiskKeys.data(), DiskKeys.size()), "Could not create xor filter"); } - static UINT8 ClusterCache[4096]; - - static UINT8* HandleCluster(MountedData* Data, UINT64 Idx) { + static void HandleCluster(MountedData* Data, UINT64 Idx, UINT8 Buffer[4096]) noexcept { if (Data->DiskFilter.Contains(Idx)) { if (Idx == 0) [[unlikely]] { - return Data->MBRData; + memcpy(Buffer, Data->MBRData, 4096); + return; } if (auto ClusterPtr = Data->Disk->try_get_cluster(Idx - 1)) { - return ClusterPtr; + memcpy(Buffer, ClusterPtr, 4096); + return; } } @@ -178,15 +171,15 @@ namespace EGL3::Service { uint64_t lIdx = 0; while (CurrentRun->count) { if (CurrentRun->idx <= Idx && uint64_t(CurrentRun->idx) + CurrentRun->count > Idx) { - Data->FileClusterCallback(File.user_context, Idx - CurrentRun->idx + lIdx, ClusterCache); - return ClusterCache; + Data->FileClusterCallback(File.user_context, Idx - CurrentRun->idx + lIdx, Buffer); + return; } lIdx += CurrentRun->count; CurrentRun++; } } - return Data->BlankData; + ZeroMemory(Buffer, 4096); } static inline BOOLEAN ExceptionFilter(ULONG Code, PEXCEPTION_POINTERS Pointers, @@ -202,88 +195,27 @@ namespace EGL3::Service { static BOOLEAN ReadCallback(SPD_STORAGE_UNIT* StorageUnit, PVOID Buffer, UINT64 BlockAddress, UINT32 BlockCount, BOOLEAN FlushFlag, - SPD_STORAGE_UNIT_STATUS* Status) + SPD_STORAGE_UNIT_STATUS* Status) noexcept { - UINT_PTR ExceptionDataAddress; - UINT64 Information, * PInformation; - //printf("read %llu %u\n", BlockAddress, BlockCount); - __try { - auto Data = (MountedData*)StorageUnit->UserContext; - while (BlockCount) { - memcpy(Buffer, HandleCluster(Data, BlockAddress), 4096); + auto Data = (MountedData*)StorageUnit->UserContext; - ++BlockAddress; - --BlockCount; - Buffer = (UINT8*)Buffer + 4096; - } - } - __except (ExceptionFilter(GetExceptionCode(), GetExceptionInformation(), &ExceptionDataAddress)) { - printf("error!\n"); - if (0 != Status) - { - PInformation = 0; - if (0 != ExceptionDataAddress) - { - Information = 4055; //(UINT64)(ExceptionDataAddress - (UINT_PTR)RawDisk->Pointer) / RawDisk->BlockLength; - PInformation = &Information; - } + while (BlockCount) { + HandleCluster(Data, BlockAddress, (UINT8*)Buffer); - SpdStorageUnitStatusSetSense(Status, SCSI_SENSE_MEDIUM_ERROR, SCSI_ADSENSE_UNRECOVERED_ERROR, PInformation); - } + ++BlockAddress; + --BlockCount; + Buffer = (UINT8*)Buffer + 4096; } - return TRUE; - } - - static BOOLEAN WriteCallback(SPD_STORAGE_UNIT* StorageUnit, - PVOID Buffer, UINT64 BlockAddress, UINT32 BlockCount, BOOLEAN FlushFlag, - SPD_STORAGE_UNIT_STATUS* Status) - { - UINT_PTR ExceptionDataAddress; - UINT64 Information, * PInformation; - - //printf("write %llu %u\n", BlockAddress, BlockCount); - __try { - auto Data = (MountedData*)StorageUnit->UserContext; - - while (BlockCount) { - UINT8* ClusBuf; - if (BlockAddress == 0) { - ClusBuf = Data->MBRData; - } - else { - ClusBuf = Data->Disk->get_cluster(BlockAddress - 1); - } - memcpy(ClusBuf, Buffer, 4096); - - ++BlockAddress; - --BlockCount; - Buffer = (UINT8*)Buffer + 4096; - } - } - __except (ExceptionFilter(GetExceptionCode(), GetExceptionInformation(), &ExceptionDataAddress)) { - printf("error!\n"); - if (0 != Status) - { - PInformation = 0; - if (0 != ExceptionDataAddress) - { - Information = 4055; //(UINT64)(ExceptionDataAddress - (UINT_PTR)RawDisk->Pointer) / RawDisk->BlockLength; - PInformation = &Information; - } - - SpdStorageUnitStatusSetSense(Status, SCSI_SENSE_MEDIUM_ERROR, SCSI_ADSENSE_UNRECOVERED_ERROR, PInformation); - } - } return TRUE; } constexpr SPD_STORAGE_UNIT_INTERFACE DiskInterface = { ReadCallback, - WriteCallback, + 0, 0, 0 }; diff --git a/src/srv/MountedDisk.h b/src/srv/MountedDisk.h index 77dbe90e..b5f0aab8 100644 --- a/src/srv/MountedDisk.h +++ b/src/srv/MountedDisk.h @@ -1,7 +1,5 @@ #pragma once -#include "../utils/Callback.h" - #include #include @@ -14,7 +12,9 @@ namespace EGL3::Service { class MountedDisk { public: - MountedDisk(const std::vector& Files, uint32_t DiskSignature); + using ClusterCallback = void (*)(void* Ctx, uint64_t LCN, uint8_t Buffer[4096]); + + MountedDisk(const std::vector& Files, uint32_t DiskSignature, ClusterCallback Callback); MountedDisk(const MountedDisk&) = delete; @@ -30,8 +30,6 @@ namespace EGL3::Service { void Unmount(); - Utils::Callback HandleFileCluster; - private: void* PrivateData; }; diff --git a/src/srv/xorfilter/xorfilter.h b/src/srv/xorfilter/xorfilter.h index 0aeaf7ed..bba114aa 100644 --- a/src/srv/xorfilter/xorfilter.h +++ b/src/srv/xorfilter/xorfilter.h @@ -9,7 +9,9 @@ class XorFilter { XorFilter(XorFilter&) = delete; - XorFilter(XorFilter&& Other) : Filter(Other.Filter) { + XorFilter(XorFilter&& Other) noexcept : + Filter(Other.Filter) + { Other.Filter.fingerprints = nullptr; }