diff --git a/.gitmodules b/.gitmodules index dce7e56..03e721f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,9 +7,6 @@ [submodule "tools/XenosRecomp"] path = tools/XenosRecomp url = https://github.com/hedge-dev/XenosRecomp.git -[submodule "thirdparty/libmspack"] - path = thirdparty/libmspack - url = https://github.com/kyz/libmspack [submodule "UnleashedRecompResources"] path = UnleashedRecompResources url = https://github.com/hedge-dev/UnleashedRecompResources.git @@ -40,9 +37,6 @@ [submodule "thirdparty/concurrentqueue"] path = thirdparty/concurrentqueue url = https://github.com/cameron314/concurrentqueue.git -[submodule "thirdparty/tiny-AES-c"] - path = thirdparty/tiny-AES-c - url = https://github.com/kokke/tiny-AES-c.git [submodule "thirdparty/magic_enum"] path = thirdparty/magic_enum url = https://github.com/Neargye/magic_enum.git diff --git a/README.md b/README.md index a70637c..5c8d648 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ``` git clone --recurse-submodules https://github.com/hedge-dev/UnleashedRecomp.git ``` -2. Decompress and decrypt `default.xex`, apply the title update patch (`default.xexp`), and place the resulting file in `./UnleashedRecompLib/private/`. +2. Place `default.xex` and `default.xexp` in `./UnleashedRecompLib/private/`. 3. Decompress `shader.ar` and place the resulting file in `./UnleashedRecompLib/private/`. 4. Open the repository directory in Visual Studio 2022 and wait for CMake generation to complete. If you don't plan to debug, switch to the `x64-Clang-Release` configuration. 5. Under Solution Explorer, right-click and choose "Switch to CMake Targets View". diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index fd372be..087b61e 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -165,10 +165,8 @@ set(UNLEASHED_RECOMP_UI_CXX_SOURCES set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES "install/installer.cpp" "install/iso_file_system.cpp" - "install/memory_mapped_file.cpp" "install/update_checker.cpp" "install/xcontent_file_system.cpp" - "install/xex_patcher.cpp" "install/hashes/apotos_shamar.cpp" "install/hashes/chunnan.cpp" "install/hashes/empire_city_adabat.cpp" @@ -201,8 +199,6 @@ set(UNLEASHED_RECOMP_THIRDPARTY_SOURCES "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot.cpp" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot_demo.cpp" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot_items.cpp" - "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/libmspack/libmspack/mspack/lzxd.c" - "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/tiny-AES-c/aes.c" "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/thirdparty/smol-v/source/smolv.cpp" ) @@ -212,11 +208,8 @@ set(UNLEASHED_RECOMP_THIRDPARTY_INCLUDES "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/json/include" - "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/libmspack/libmspack/mspack" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/magic_enum/include" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/stb" - "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/tiny-AES-c" - "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/TinySHA1" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/unordered_dense/include" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/volk" "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/Vulkan-Headers/include" diff --git a/UnleashedRecomp/install/installer.cpp b/UnleashedRecomp/install/installer.cpp index 8a3e7b3..9574c5d 100644 --- a/UnleashedRecomp/install/installer.cpp +++ b/UnleashedRecomp/install/installer.cpp @@ -598,5 +598,5 @@ XexPatcher::Result Installer::checkGameUpdateCompatibility(const std::filesystem } std::vector patchedBytes; - return XexPatcher::apply(xexBytes, patchBytes, patchedBytes, true); + return XexPatcher::apply(xexBytes.data(), xexBytes.size(), patchBytes.data(), patchBytes.size(), patchedBytes, true); } diff --git a/UnleashedRecomp/install/installer.h b/UnleashedRecomp/install/installer.h index 198076d..9f216a2 100644 --- a/UnleashedRecomp/install/installer.h +++ b/UnleashedRecomp/install/installer.h @@ -4,7 +4,7 @@ #include #include "virtual_file_system.h" -#include "xex_patcher.h" +#include enum class DLC { Unknown, diff --git a/UnleashedRecomp/install/iso_file_system.h b/UnleashedRecomp/install/iso_file_system.h index 9e62870..dceca07 100644 --- a/UnleashedRecomp/install/iso_file_system.h +++ b/UnleashedRecomp/install/iso_file_system.h @@ -16,7 +16,7 @@ #include "virtual_file_system.h" -#include "memory_mapped_file.h" +#include struct ISOFileSystem : VirtualFileSystem { diff --git a/UnleashedRecomp/install/memory_mapped_file.cpp b/UnleashedRecomp/install/memory_mapped_file.cpp deleted file mode 100644 index ba3c5d8..0000000 --- a/UnleashedRecomp/install/memory_mapped_file.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "memory_mapped_file.h" - -#if !defined(_WIN32) -# include -# include -# include -# include -#endif - -MemoryMappedFile::MemoryMappedFile() -{ - // Default constructor. -} - -MemoryMappedFile::MemoryMappedFile(const std::filesystem::path &path) -{ - open(path); -} - -MemoryMappedFile::~MemoryMappedFile() -{ - close(); -} - -MemoryMappedFile::MemoryMappedFile(MemoryMappedFile &&other) -{ -#if defined(_WIN32) - fileHandle = other.fileHandle; - fileMappingHandle = other.fileMappingHandle; - fileView = other.fileView; - fileSize = other.fileSize; - - other.fileHandle = nullptr; - other.fileMappingHandle = nullptr; - other.fileView = nullptr; - other.fileSize.QuadPart = 0; -#else - fileHandle = other.fileHandle; - fileView = other.fileView; - fileSize = other.fileSize; - - other.fileHandle = -1; - other.fileView = MAP_FAILED; - other.fileSize = 0; -#endif -} - -bool MemoryMappedFile::open(const std::filesystem::path &path) -{ -#if defined(_WIN32) - fileHandle = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if (fileHandle == INVALID_HANDLE_VALUE) - { - fprintf(stderr, "CreateFileW failed with error %lu.\n", GetLastError()); - fileHandle = nullptr; - return false; - } - - if (!GetFileSizeEx(fileHandle, &fileSize)) - { - fprintf(stderr, "GetFileSizeEx failed with error %lu.\n", GetLastError()); - CloseHandle(fileHandle); - fileHandle = nullptr; - return false; - } - - fileMappingHandle = CreateFileMappingW(fileHandle, nullptr, PAGE_READONLY, 0, 0, nullptr); - if (fileMappingHandle == nullptr) - { - fprintf(stderr, "CreateFileMappingW failed with error %lu.\n", GetLastError()); - CloseHandle(fileHandle); - fileHandle = nullptr; - return false; - } - - fileView = MapViewOfFile(fileMappingHandle, FILE_MAP_READ, 0, 0, 0); - if (fileView == nullptr) - { - fprintf(stderr, "MapViewOfFile failed with error %lu.\n", GetLastError()); - CloseHandle(fileMappingHandle); - CloseHandle(fileHandle); - fileMappingHandle = nullptr; - fileHandle = nullptr; - return false; - } - - return true; -#else - fileHandle = ::open(path.c_str(), O_RDONLY); - if (fileHandle == -1) - { - fprintf(stderr, "open for %s failed with error %s.\n", path.c_str(), strerror(errno)); - return false; - } - - fileSize = lseek(fileHandle, 0, SEEK_END); - if (fileSize == (off_t)(-1)) - { - fprintf(stderr, "lseek failed with error %s.\n", strerror(errno)); - ::close(fileHandle); - fileHandle = -1; - return false; - } - - fileView = mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fileHandle, 0); - if (fileView == MAP_FAILED) - { - fprintf(stderr, "mmap failed with error %s.\n", strerror(errno)); - ::close(fileHandle); - fileHandle = -1; - return false; - } - - return true; -#endif -} - -void MemoryMappedFile::close() -{ -#if defined(_WIN32) - if (fileView != nullptr) - { - UnmapViewOfFile(fileView); - } - - if (fileMappingHandle != nullptr) - { - CloseHandle(fileMappingHandle); - } - - if (fileHandle != nullptr) - { - CloseHandle(fileHandle); - } -#else - if (fileView != MAP_FAILED) - { - munmap(fileView, fileSize); - } - - if (fileHandle != -1) - { - ::close(fileHandle); - } -#endif -} - -bool MemoryMappedFile::isOpen() const -{ -#if defined(_WIN32) - return (fileView != nullptr); -#else - return (fileView != MAP_FAILED); -#endif -} - -uint8_t *MemoryMappedFile::data() const -{ - return reinterpret_cast(fileView); -} - -size_t MemoryMappedFile::size() const -{ -#if defined(_WIN32) - return fileSize.QuadPart; -#else - return static_cast(fileSize); -#endif -} diff --git a/UnleashedRecomp/install/memory_mapped_file.h b/UnleashedRecomp/install/memory_mapped_file.h deleted file mode 100644 index a3de88b..0000000 --- a/UnleashedRecomp/install/memory_mapped_file.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#if defined(_WIN32) -# include -#else -# include -#endif - -struct MemoryMappedFile { -#if defined(_WIN32) - HANDLE fileHandle = nullptr; - HANDLE fileMappingHandle = nullptr; - LPVOID fileView = nullptr; - LARGE_INTEGER fileSize = {}; -#else - int fileHandle = -1; - void *fileView = MAP_FAILED; - off_t fileSize = 0; -#endif - - MemoryMappedFile(); - MemoryMappedFile(const std::filesystem::path &path); - MemoryMappedFile(MemoryMappedFile &&other); - ~MemoryMappedFile(); - bool open(const std::filesystem::path &path); - void close(); - bool isOpen() const; - uint8_t *data() const; - size_t size() const; -}; diff --git a/UnleashedRecomp/install/xcontent_file_system.h b/UnleashedRecomp/install/xcontent_file_system.h index dc36a2c..c776975 100644 --- a/UnleashedRecomp/install/xcontent_file_system.h +++ b/UnleashedRecomp/install/xcontent_file_system.h @@ -16,7 +16,7 @@ #include "virtual_file_system.h" -#include "memory_mapped_file.h" +#include enum class XContentVolumeType { diff --git a/UnleashedRecomp/install/xex_patcher.cpp b/UnleashedRecomp/install/xex_patcher.cpp deleted file mode 100644 index 4e35c1c..0000000 --- a/UnleashedRecomp/install/xex_patcher.cpp +++ /dev/null @@ -1,693 +0,0 @@ -// Referenced from: https://github.com/xenia-canary/xenia-canary/blob/canary_experimental/src/xenia/cpu/xex_module.cc - -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xex_patcher.h" - -#include -#include - -#include -#include -#include -#include - -#include "memory_mapped_file.h" - -enum Xex2ModuleFlags -{ - XEX_MODULE_MODULE_PATCH = 0x10, - XEX_MODULE_PATCH_FULL = 0x20, - XEX_MODULE_PATCH_DELTA = 0x40, -}; - -enum Xex2HeaderKeys -{ - XEX_HEADER_FILE_FORMAT_INFO = 0x3FF, - XEX_HEADER_DELTA_PATCH_DESCRIPTOR = 0x5FF, -}; - -enum Xex2EncryptionType -{ - XEX_ENCRYPTION_NONE = 0, - XEX_ENCRYPTION_NORMAL = 1, -}; - -enum Xex2CompressionType -{ - XEX_COMPRESSION_NONE = 0, - XEX_COMPRESSION_BASIC = 1, - XEX_COMPRESSION_NORMAL = 2, - XEX_COMPRESSION_DELTA = 3, -}; - -enum Xex2SectionType -{ - XEX_SECTION_CODE = 1, - XEX_SECTION_DATA = 2, - XEX_SECTION_READONLY_DATA = 3, -}; - -struct Xex2OptHeader -{ - be key; - - union - { - be value; - be offset; - }; -}; - -struct Xex2Header -{ - be magic; - be moduleFlags; - be headerSize; - be reserved; - be securityOffset; - be headerCount; - Xex2OptHeader headers[1]; -}; - -struct Xex2PageDescriptor -{ - union - { - // Must be endian-swapped before reading the bitfield. - uint32_t beValue; - struct - { - uint32_t info : 4; - uint32_t pageCount : 28; - }; - }; - - char dataDigest[0x14]; -}; - -struct Xex2SecurityInfo -{ - be headerSize; - be imageSize; - char rsaSignature[0x100]; - be unknown; - be imageFlags; - be loadAddress; - char sectionDigest[0x14]; - be importTableCount; - char importTableDigest[0x14]; - char xgd2MediaId[0x10]; - char aesKey[0x10]; - be exportTable; - char headerDigest[0x14]; - be region; - be allowedMediaTypes; - be pageDescriptorCount; - Xex2PageDescriptor pageDescriptors[1]; -}; - -struct Xex2DeltaPatch -{ - be oldAddress; - be newAddress; - be uncompressedLength; - be compressedLength; - char patchData[1]; -}; - -struct Xex2OptDeltaPatchDescriptor -{ - be size; - be targetVersionValue; - be sourceVersionValue; - uint8_t digestSource[0x14]; - uint8_t imageKeySource[0x10]; - be sizeOfTargetHeaders; - be deltaHeadersSourceOffset; - be deltaHeadersSourceSize; - be deltaHeadersTargetOffset; - be deltaImageSourceOffset; - be deltaImageSourceSize; - be deltaImageTargetOffset; - Xex2DeltaPatch info; -}; - -struct Xex2FileBasicCompressionBlock -{ - be dataSize; - be zeroSize; -}; - -struct Xex2FileBasicCompressionInfo -{ - Xex2FileBasicCompressionBlock firstBlock; -}; - -struct Xex2CompressedBlockInfo -{ - be blockSize; - uint8_t blockHash[20]; -}; - -struct Xex2FileNormalCompressionInfo -{ - be windowSize; - Xex2CompressedBlockInfo firstBlock; -}; - -struct Xex2OptFileFormatInfo -{ - be infoSize; - be encryptionType; - be compressionType; - union - { - Xex2FileBasicCompressionInfo basic; - Xex2FileNormalCompressionInfo normal; - } compressionInfo; -}; - -static const void *getOptHeaderPtr(std::span moduleBytes, uint32_t headerKey) -{ - if ((headerKey & 0xFF) == 0) - { - assert(false && "Wrong type of method for this key. Expected return value is a number."); - return nullptr; - } - - const Xex2Header *xex2Header = (const Xex2Header *)(moduleBytes.data()); - for (uint32_t i = 0; i < xex2Header->headerCount; i++) - { - const Xex2OptHeader &optHeader = xex2Header->headers[i]; - if (optHeader.key == headerKey) - { - if ((headerKey & 0xFF) == 1) - { - return &optHeader.value; - } - else - { - return &moduleBytes.data()[optHeader.offset]; - } - } - } - - return nullptr; -} - -struct mspack_memory_file -{ - mspack_system sys; - void *buffer; - size_t bufferSize; - size_t offset; -}; - -static mspack_memory_file *mspack_memory_open(mspack_system *sys, void *buffer, size_t bufferSize) -{ - assert(bufferSize < INT_MAX); - - if (bufferSize >= INT_MAX) - { - return nullptr; - } - - mspack_memory_file *memoryFile = (mspack_memory_file *)(std::calloc(1, sizeof(mspack_memory_file))); - if (memoryFile == nullptr) - { - return memoryFile; - } - - memoryFile->buffer = buffer; - memoryFile->bufferSize = bufferSize; - memoryFile->offset = 0; - return memoryFile; -} - -static void mspack_memory_close(mspack_memory_file *file) -{ - std::free(file); -} - -static int mspack_memory_read(mspack_file *file, void *buffer, int chars) -{ - mspack_memory_file *memoryFile = (mspack_memory_file *)(file); - const size_t remaining = memoryFile->bufferSize - memoryFile->offset; - const size_t total = std::min(size_t(chars), remaining); - std::memcpy(buffer, (uint8_t *)(memoryFile->buffer) + memoryFile->offset, total); - memoryFile->offset += total; - return int(total); -} - -static int mspack_memory_write(mspack_file *file, void *buffer, int chars) -{ - mspack_memory_file *memoryFile = (mspack_memory_file *)(file); - const size_t remaining = memoryFile->bufferSize - memoryFile->offset; - const size_t total = std::min(size_t(chars), remaining); - std::memcpy((uint8_t *)(memoryFile->buffer) + memoryFile->offset, buffer, total); - memoryFile->offset += total; - return int(total); -} - -static void *mspack_memory_alloc(mspack_system *sys, size_t chars) -{ - return std::calloc(chars, 1); -} - -static void mspack_memory_free(void *ptr) -{ - std::free(ptr); -} - -static void mspack_memory_copy(void *src, void *dest, size_t chars) -{ - std::memcpy(dest, src, chars); -} - -static mspack_system *mspack_memory_sys_create() -{ - auto sys = (mspack_system *)(std::calloc(1, sizeof(mspack_system))); - if (!sys) - { - return nullptr; - } - - sys->read = mspack_memory_read; - sys->write = mspack_memory_write; - sys->alloc = mspack_memory_alloc; - sys->free = mspack_memory_free; - sys->copy = mspack_memory_copy; - return sys; -} - -static void mspack_memory_sys_destroy(struct mspack_system *sys) -{ - free(sys); -} - -#if defined(_WIN32) -inline bool bitScanForward(uint32_t v, uint32_t *outFirstSetIndex) -{ - return _BitScanForward((unsigned long *)(outFirstSetIndex), v) != 0; -} - -inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex) -{ - return _BitScanForward64((unsigned long *)(outFirstSetIndex), v) != 0; -} - -#else -inline bool bitScanForward(uint32_t v, uint32_t *outFirstSetIndex) -{ - int i = ffs(v); - *outFirstSetIndex = i - 1; - return i != 0; -} - -inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex) -{ - int i = __builtin_ffsll(v); - *outFirstSetIndex = i - 1; - return i != 0; -} -#endif - -static int lzxDecompress(const void *lzxData, size_t lzxLength, void *dst, size_t dstLength, uint32_t windowSize, void *windowData, size_t windowDataLength) -{ - int resultCode = 1; - uint32_t windowBits; - if (!bitScanForward(windowSize, &windowBits)) { - return resultCode; - } - - mspack_system *sys = mspack_memory_sys_create(); - mspack_memory_file *lzxSrc = mspack_memory_open(sys, (void *)(lzxData), lzxLength); - mspack_memory_file *lzxDst = mspack_memory_open(sys, dst, dstLength); - lzxd_stream *lzxd = lzxd_init(sys, (mspack_file *)(lzxSrc), (mspack_file *)(lzxDst), windowBits, 0, 0x8000, dstLength, 0); - if (lzxd != nullptr) { - if (windowData != nullptr) { - size_t paddingLength = windowSize - windowDataLength; - std::memset(&lzxd->window[0], 0, paddingLength); - std::memcpy(&lzxd->window[paddingLength], windowData, windowDataLength); - lzxd->ref_data_size = windowSize; - } - - resultCode = lzxd_decompress(lzxd, dstLength); - lzxd_free(lzxd); - } - - if (lzxSrc) { - mspack_memory_close(lzxSrc); - } - - if (lzxDst) { - mspack_memory_close(lzxDst); - } - - if (sys) { - mspack_memory_sys_destroy(sys); - } - - return resultCode; -} - -static int lzxDeltaApplyPatch(const Xex2DeltaPatch *deltaPatch, uint32_t patchLength, uint32_t windowSize, uint8_t *dstData) -{ - const void *patchEnd = (const uint8_t *)(deltaPatch) + patchLength; - const Xex2DeltaPatch *curPatch = deltaPatch; - while (patchEnd > curPatch) - { - int patchSize = -4; - if (curPatch->compressedLength == 0 && curPatch->uncompressedLength == 0 && curPatch->newAddress == 0 && curPatch->oldAddress == 0) - { - // End of patch. - break; - } - - switch (curPatch->compressedLength) - { - case 0: - // Set the data to zeroes. - std::memset(&dstData[curPatch->newAddress], 0, curPatch->uncompressedLength); - break; - case 1: - // Move the data. - std::memcpy(&dstData[curPatch->newAddress], &dstData[curPatch->oldAddress], curPatch->uncompressedLength); - break; - default: - // Decompress the data into the destination. - patchSize = curPatch->compressedLength - 4; - int result = lzxDecompress(curPatch->patchData, curPatch->compressedLength, &dstData[curPatch->newAddress], curPatch->uncompressedLength, windowSize, &dstData[curPatch->oldAddress], curPatch->uncompressedLength); - if (result != 0) - { - return result; - } - - break; - } - - curPatch++; - curPatch = (const Xex2DeltaPatch *)((const uint8_t *)(curPatch) + patchSize); - } - - return 0; -} - -XexPatcher::Result XexPatcher::apply(std::span xexBytes, std::span patchBytes, std::vector &outBytes, bool skipData) -{ - // Validate headers. - static const char Xex2Magic[] = "XEX2"; - const Xex2Header *xexHeader = (const Xex2Header *)(xexBytes.data()); - if (memcmp(xexBytes.data(), Xex2Magic, 4) != 0) - { - return Result::XexFileInvalid; - } - - const Xex2Header *patchHeader = (const Xex2Header *)(patchBytes.data()); - if (memcmp(patchBytes.data(), Xex2Magic, 4) != 0) - { - return Result::PatchFileInvalid; - } - - if ((patchHeader->moduleFlags & (XEX_MODULE_MODULE_PATCH | XEX_MODULE_PATCH_DELTA | XEX_MODULE_PATCH_FULL)) == 0) - { - return Result::PatchFileInvalid; - } - - // Validate patch. - const Xex2OptDeltaPatchDescriptor *patchDescriptor = (const Xex2OptDeltaPatchDescriptor *)(getOptHeaderPtr(patchBytes, XEX_HEADER_DELTA_PATCH_DESCRIPTOR)); - if (patchDescriptor == nullptr) - { - return Result::PatchFileInvalid; - } - - const Xex2OptFileFormatInfo *patchFileFormatInfo = (const Xex2OptFileFormatInfo *)(getOptHeaderPtr(patchBytes, XEX_HEADER_FILE_FORMAT_INFO)); - if (patchFileFormatInfo == nullptr) - { - return Result::PatchFileInvalid; - } - - if (patchFileFormatInfo->compressionType != XEX_COMPRESSION_DELTA) - { - return Result::PatchFileInvalid; - } - - if (patchDescriptor->deltaHeadersSourceOffset > xexHeader->headerSize) - { - return Result::PatchIncompatible; - } - - if (patchDescriptor->deltaHeadersSourceSize > (xexHeader->headerSize - patchDescriptor->deltaHeadersSourceOffset)) - { - return Result::PatchIncompatible; - } - - if (patchDescriptor->deltaHeadersTargetOffset > patchDescriptor->sizeOfTargetHeaders) - { - return Result::PatchIncompatible; - } - - uint32_t deltaTargetSize = patchDescriptor->sizeOfTargetHeaders - patchDescriptor->deltaHeadersTargetOffset; - if (patchDescriptor->deltaHeadersSourceSize > deltaTargetSize) - { - return Result::PatchIncompatible; - } - - // Apply patch. - uint32_t headerTargetSize = patchDescriptor->sizeOfTargetHeaders; - if (headerTargetSize == 0) - { - headerTargetSize = patchDescriptor->deltaHeadersTargetOffset + patchDescriptor->deltaHeadersSourceSize; - } - - // Create the bytes for the new XEX header. Copy over the existing data. - uint32_t newXexHeaderSize = std::max(headerTargetSize, xexHeader->headerSize.get()); - outBytes.resize(newXexHeaderSize); - memset(outBytes.data(), 0, newXexHeaderSize); - memcpy(outBytes.data(), xexBytes.data(), headerTargetSize); - - Xex2Header *newXexHeader = (Xex2Header *)(outBytes.data()); - if (patchDescriptor->deltaHeadersSourceOffset > 0) - { - memcpy(&outBytes[patchDescriptor->deltaHeadersTargetOffset], &outBytes[patchDescriptor->deltaHeadersSourceOffset], patchDescriptor->deltaHeadersSourceSize); - } - - int resultCode = lzxDeltaApplyPatch(&patchDescriptor->info, patchDescriptor->size, patchFileFormatInfo->compressionInfo.normal.windowSize, outBytes.data()); - if (resultCode != 0) - { - return Result::PatchFailed; - } - - // Make the header the specified size by the patch. - outBytes.resize(headerTargetSize); - newXexHeader = (Xex2Header *)(outBytes.data()); - - // Copy the rest of the data. - const Xex2SecurityInfo *newSecurityInfo = (const Xex2SecurityInfo *)(&outBytes[newXexHeader->securityOffset]); - outBytes.resize(outBytes.size() + newSecurityInfo->imageSize); - memset(&outBytes[headerTargetSize], 0, outBytes.size() - headerTargetSize); - memcpy(&outBytes[headerTargetSize], &xexBytes[xexHeader->headerSize], xexBytes.size() - xexHeader->headerSize); - newXexHeader = (Xex2Header *)(outBytes.data()); - newSecurityInfo = (const Xex2SecurityInfo *)(&outBytes[newXexHeader->securityOffset]); - - // Decrypt the keys and validate that the patch is compatible with the base file. - static const uint32_t KeySize = 16; - static const uint8_t Xex2RetailKey[16] = { 0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3, 0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91 }; - static const uint8_t AESBlankIV[AES_BLOCKLEN] = {}; - const Xex2SecurityInfo *originalSecurityInfo = (const Xex2SecurityInfo *)(&xexBytes[xexHeader->securityOffset]); - const Xex2SecurityInfo *patchSecurityInfo = (const Xex2SecurityInfo *)(&patchBytes[patchHeader->securityOffset]); - uint8_t decryptedOriginalKey[KeySize]; - uint8_t decryptedNewKey[KeySize]; - uint8_t decryptedPatchKey[KeySize]; - uint8_t decrpytedImageKeySource[KeySize]; - memcpy(decryptedOriginalKey, originalSecurityInfo->aesKey, KeySize); - memcpy(decryptedNewKey, newSecurityInfo->aesKey, KeySize); - memcpy(decryptedPatchKey, patchSecurityInfo->aesKey, KeySize); - memcpy(decrpytedImageKeySource, patchDescriptor->imageKeySource, KeySize); - - AES_ctx aesContext; - AES_init_ctx_iv(&aesContext, Xex2RetailKey, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, decryptedOriginalKey, KeySize); - - AES_ctx_set_iv(&aesContext, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, decryptedNewKey, KeySize); - - AES_init_ctx_iv(&aesContext, decryptedNewKey, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, decryptedPatchKey, KeySize); - - AES_ctx_set_iv(&aesContext, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, decrpytedImageKeySource, KeySize); - - // Validate the patch's key matches the one from the original XEX. - if (memcmp(decrpytedImageKeySource, decryptedOriginalKey, KeySize) != 0) - { - return Result::PatchIncompatible; - } - - // Don't process the rest of the patch. - if (skipData) - { - return Result::Success; - } - - // Decrypt base XEX if necessary. - const Xex2OptFileFormatInfo *fileFormatInfo = (const Xex2OptFileFormatInfo *)(getOptHeaderPtr(xexBytes, XEX_HEADER_FILE_FORMAT_INFO)); - if (fileFormatInfo == nullptr) - { - return Result::XexFileInvalid; - } - - if (fileFormatInfo->encryptionType == XEX_ENCRYPTION_NORMAL) - { - AES_init_ctx_iv(&aesContext, decryptedOriginalKey, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, &outBytes[headerTargetSize], xexBytes.size() - xexHeader->headerSize); - } - else if (fileFormatInfo->encryptionType != XEX_ENCRYPTION_NONE) - { - return Result::XexFileInvalid; - } - - // Decompress base XEX if necessary. - if (fileFormatInfo->compressionType == XEX_COMPRESSION_BASIC) - { - const Xex2FileBasicCompressionBlock *blocks = &fileFormatInfo->compressionInfo.basic.firstBlock; - int32_t numBlocks = (fileFormatInfo->infoSize / sizeof(Xex2FileBasicCompressionBlock)) - 1; - int32_t baseCompressedSize = 0; - int32_t baseImageSize = 0; - for (int32_t i = 0; i < numBlocks; i++) { - baseCompressedSize += blocks[i].dataSize; - baseImageSize += blocks[i].dataSize + blocks[i].zeroSize; - } - - if (outBytes.size() < (headerTargetSize + baseImageSize)) - { - return Result::XexFileInvalid; - } - - // Reverse iteration allows to perform this decompression in place. - uint8_t *srcDataCursor = outBytes.data() + headerTargetSize + baseCompressedSize; - uint8_t *outDataCursor = outBytes.data() + headerTargetSize + baseImageSize; - for (int32_t i = numBlocks - 1; i >= 0; i--) - { - outDataCursor -= blocks[i].zeroSize; - memset(outDataCursor, 0, blocks[i].zeroSize); - outDataCursor -= blocks[i].dataSize; - srcDataCursor -= blocks[i].dataSize; - memmove(outDataCursor, srcDataCursor, blocks[i].dataSize); - } - } - else if (fileFormatInfo->compressionType == XEX_COMPRESSION_NORMAL || fileFormatInfo->compressionType == XEX_COMPRESSION_DELTA) - { - return Result::XexFileUnsupported; - } - else if (fileFormatInfo->compressionType != XEX_COMPRESSION_NONE) - { - return Result::XexFileInvalid; - } - - Xex2OptFileFormatInfo *newFileFormatInfo = (Xex2OptFileFormatInfo *)(getOptHeaderPtr(outBytes, XEX_HEADER_FILE_FORMAT_INFO)); - if (newFileFormatInfo == nullptr) - { - return Result::PatchFailed; - } - - // Update the header to indicate no encryption or compression is used. - newFileFormatInfo->encryptionType = XEX_ENCRYPTION_NONE; - newFileFormatInfo->compressionType = XEX_COMPRESSION_NONE; - - // Copy and decrypt patch data if necessary. - std::vector patchData; - patchData.resize(patchBytes.size() - patchHeader->headerSize); - memcpy(patchData.data(), &patchBytes[patchHeader->headerSize], patchData.size()); - - if (patchFileFormatInfo->encryptionType == XEX_ENCRYPTION_NORMAL) - { - AES_init_ctx_iv(&aesContext, decryptedPatchKey, AESBlankIV); - AES_CBC_decrypt_buffer(&aesContext, patchData.data(), patchData.size()); - } - else if (patchFileFormatInfo->encryptionType != XEX_ENCRYPTION_NONE) - { - return Result::PatchFileInvalid; - } - - const Xex2CompressedBlockInfo *currentBlock = &patchFileFormatInfo->compressionInfo.normal.firstBlock; - uint8_t *outExe = &outBytes[newXexHeader->headerSize]; - if (patchDescriptor->deltaImageSourceOffset > 0) - { - memcpy(&outExe[patchDescriptor->deltaImageTargetOffset], &outExe[patchDescriptor->deltaImageSourceOffset], patchDescriptor->deltaImageSourceSize); - } - - static const uint32_t DigestSize = 20; - uint8_t sha1Digest[DigestSize]; - sha1::SHA1 sha1Context; - uint8_t *patchDataCursor = patchData.data(); - while (currentBlock->blockSize > 0) - { - const Xex2CompressedBlockInfo *nextBlock = (const Xex2CompressedBlockInfo *)(patchDataCursor); - - // Hash and validate the block. - sha1Context.reset(); - sha1Context.processBytes(patchDataCursor, currentBlock->blockSize); - sha1Context.finalize(sha1Digest); - if (memcmp(sha1Digest, currentBlock->blockHash, DigestSize) != 0) - { - return Result::PatchFailed; - } - - patchDataCursor += 24; - - // Apply the block's patch data. - uint32_t blockDataSize = currentBlock->blockSize - 24; - if (lzxDeltaApplyPatch((const Xex2DeltaPatch *)(patchDataCursor), blockDataSize, patchFileFormatInfo->compressionInfo.normal.windowSize, outExe) != 0) - { - return Result::PatchFailed; - } - - patchDataCursor += blockDataSize; - currentBlock = nextBlock; - } - - return Result::Success; -} - -XexPatcher::Result XexPatcher::apply(const std::filesystem::path &baseXexPath, const std::filesystem::path &patchXexPath, const std::filesystem::path &newXexPath) -{ - MemoryMappedFile baseXexFile(baseXexPath); - MemoryMappedFile patchFile(patchXexPath); - if (!baseXexFile.isOpen() || !patchFile.isOpen()) - { - return Result::FileOpenFailed; - } - - std::vector newXexBytes; - Result result = apply({ baseXexFile.data(), baseXexFile.size() }, { patchFile.data(), patchFile.size() }, newXexBytes, false); - if (result != Result::Success) - { - return result; - } - - std::ofstream newXexFile(newXexPath, std::ios::binary); - if (!newXexFile.is_open()) - { - return Result::FileOpenFailed; - } - - newXexFile.write((const char *)(newXexBytes.data()), newXexBytes.size()); - newXexFile.close(); - - if (newXexFile.bad()) - { - std::filesystem::remove(newXexPath); - return Result::FileWriteFailed; - } - - return Result::Success; -} diff --git a/UnleashedRecomp/install/xex_patcher.h b/UnleashedRecomp/install/xex_patcher.h deleted file mode 100644 index c86ed75..0000000 --- a/UnleashedRecomp/install/xex_patcher.h +++ /dev/null @@ -1,35 +0,0 @@ -// Referenced from: https://github.com/xenia-canary/xenia-canary/blob/canary_experimental/src/xenia/cpu/xex_module.cc - -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2023 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#pragma once - -#include -#include -#include -#include - -struct XexPatcher -{ - enum class Result { - Success, - FileOpenFailed, - FileWriteFailed, - XexFileUnsupported, - XexFileInvalid, - PatchFileInvalid, - PatchIncompatible, - PatchFailed, - PatchUnsupported - }; - - static Result apply(std::span xexBytes, std::span patchBytes, std::vector &outBytes, bool skipData); - static Result apply(const std::filesystem::path &baseXexPath, const std::filesystem::path &patchXexPath, const std::filesystem::path &newXexPath); -}; diff --git a/UnleashedRecomp/main.cpp b/UnleashedRecomp/main.cpp index 18507c3..a513994 100644 --- a/UnleashedRecomp/main.cpp +++ b/UnleashedRecomp/main.cpp @@ -106,33 +106,33 @@ uint32_t LdrLoadModule(const std::filesystem::path &path) return 0; } - auto* xex = reinterpret_cast(loadResult.data()); - auto security = reinterpret_cast((char*)xex + xex->AddressOfSecurityInfo); - - auto format = Xex2FindOptionalHeader(xex, XEX_HEADER_FILE_FORMAT_INFO); - auto entry = *Xex2FindOptionalHeader(xex, XEX_HEADER_ENTRY_POINT); + auto* header = reinterpret_cast(loadResult.data()); + auto* security = reinterpret_cast(loadResult.data() + header->securityOffset); + const auto* fileFormatInfo = reinterpret_cast(getOptHeaderPtr(loadResult.data(), XEX_HEADER_FILE_FORMAT_INFO)); + auto entry = *reinterpret_cast(getOptHeaderPtr(loadResult.data(), XEX_HEADER_ENTRY_POINT)); ByteSwapInplace(entry); - auto srcData = (char *)xex + xex->SizeOfHeader; - auto destData = (char *)g_memory.Translate(security->ImageBase); - if (format->CompressionType == 0) + auto srcData = loadResult.data() + header->headerSize; + auto destData = reinterpret_cast(g_memory.Translate(security->loadAddress)); + + if (fileFormatInfo->compressionType == XEX_COMPRESSION_NONE) { - memcpy(destData, srcData, security->SizeOfImage); + memcpy(destData, srcData, security->imageSize); } - else if (format->CompressionType == 1) + else if (fileFormatInfo->compressionType == XEX_COMPRESSION_BASIC) { - auto numBlocks = (format->SizeOfHeader / sizeof(XEX_BASIC_FILE_COMPRESSION_INFO)) - 1; - auto blocks = reinterpret_cast(format + 1); + auto* blocks = reinterpret_cast(fileFormatInfo + 1); + const size_t numBlocks = (fileFormatInfo->infoSize / sizeof(Xex2FileBasicCompressionInfo)) - 1; for (size_t i = 0; i < numBlocks; i++) { - memcpy(destData, srcData, blocks[i].SizeOfData); + memcpy(destData, srcData, blocks[i].dataSize); - srcData += blocks[i].SizeOfData; - destData += blocks[i].SizeOfData; - memset(destData, 0, blocks[i].SizeOfPadding); + srcData += blocks[i].dataSize; + destData += blocks[i].dataSize; - destData += blocks[i].SizeOfPadding; + memset(destData, 0, blocks[i].zeroSize); + destData += blocks[i].zeroSize; } } else @@ -140,9 +140,9 @@ uint32_t LdrLoadModule(const std::filesystem::path &path) assert(false && "Unknown compression type."); } - auto res = Xex2FindOptionalHeader(xex, XEX_HEADER_RESOURCE_INFO); + auto res = reinterpret_cast(getOptHeaderPtr(loadResult.data(), XEX_HEADER_RESOURCE_INFO)); - g_xdbfWrapper = XDBFWrapper((uint8_t*)g_memory.Translate(res->Offset.get()), res->SizeOfData); + g_xdbfWrapper = XDBFWrapper((uint8_t*)g_memory.Translate(res->offset.get()), res->sizeOfData); return entry; } diff --git a/UnleashedRecompLib/CMakeLists.txt b/UnleashedRecompLib/CMakeLists.txt index ac77493..4edc949 100644 --- a/UnleashedRecompLib/CMakeLists.txt +++ b/UnleashedRecompLib/CMakeLists.txt @@ -28,7 +28,10 @@ endforeach() add_custom_command( OUTPUT ${UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES} COMMAND $ - DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex" "${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml" + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex" + "${CMAKE_CURRENT_SOURCE_DIR}/private/default.xexp" + "${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml" ) set(XENOS_RECOMP_ROOT "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/XenosRecomp") diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 0b0ed1a..6f5781c 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -1,5 +1,7 @@ [main] file_path = "../private/default.xex" +patch_file_path = "../private/default.xexp" +patched_file_path = "../private/default_patched.xex" out_directory_path = "../ppc" switch_table_file_path = "SWA_switch_tables.toml" diff --git a/thirdparty/TinySHA1/TinySHA1.hpp b/thirdparty/TinySHA1/TinySHA1.hpp deleted file mode 100644 index 2493e88..0000000 --- a/thirdparty/TinySHA1/TinySHA1.hpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * - * TinySHA1 - a header only implementation of the SHA1 algorithm in C++. Based - * on the implementation in boost::uuid::details. - * - * SHA1 Wikipedia Page: http://en.wikipedia.org/wiki/SHA-1 - * - * Copyright (c) 2012-22 SAURAV MOHAPATRA - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Taken from https://github.com/mohaps/TinySHA1 - * Modified for use by Xenia - */ -#ifndef _TINY_SHA1_HPP_ -#define _TINY_SHA1_HPP_ - -#include -#include -#include -#include - -namespace sha1 { -class SHA1 { - public: - typedef uint32_t digest32_t[5]; - typedef uint8_t digest8_t[20]; - inline static uint32_t LeftRotate(uint32_t value, size_t count) { - return (value << count) ^ (value >> (32 - count)); - } - SHA1() { reset(); } - virtual ~SHA1() {} - SHA1(const SHA1& s) { *this = s; } - const SHA1& operator=(const SHA1& s) { - memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t)); - memcpy(m_block, s.m_block, 64); - m_blockByteIndex = s.m_blockByteIndex; - m_byteCount = s.m_byteCount; - - return *this; - } - - SHA1& init(const uint32_t digest[5], const uint8_t block[64], - uint32_t count) { - std::memcpy(m_digest, digest, 20); - std::memcpy(m_block, block, count % 64); - m_byteCount = count; - m_blockByteIndex = count % 64; - - return *this; - } - - const uint32_t* getDigest() const { return m_digest; } - const uint8_t* getBlock() const { return m_block; } - size_t getBlockByteIndex() const { return m_blockByteIndex; } - size_t getByteCount() const { return m_byteCount; } - - SHA1& reset() { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; - return *this; - } - - SHA1& processByte(uint8_t octet) { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == 64) { - this->m_blockByteIndex = 0; - processBlock(); - } - - return *this; - } - - SHA1& processBlock(const void* const start, const void* const end) { - const uint8_t* begin = static_cast(start); - const uint8_t* finish = static_cast(end); - while (begin != finish) { - processByte(*begin); - begin++; - } - return *this; - } - - SHA1& processBytes(const void* const data, size_t len) { - const uint8_t* block = static_cast(data); - processBlock(block, block + len); - return *this; - } - - const uint32_t* finalize(digest32_t digest) { - size_t bitCount = this->m_byteCount * 8; - processByte(0x80); - if (this->m_blockByteIndex > 56) { - while (m_blockByteIndex != 0) { - processByte(0); - } - while (m_blockByteIndex < 56) { - processByte(0); - } - } else { - while (m_blockByteIndex < 56) { - processByte(0); - } - } - processByte(0); - processByte(0); - processByte(0); - processByte(0); - processByte(static_cast((bitCount >> 24) & 0xFF)); - processByte(static_cast((bitCount >> 16) & 0xFF)); - processByte(static_cast((bitCount >> 8) & 0xFF)); - processByte(static_cast((bitCount)&0xFF)); - - memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; - } - - const uint8_t* finalize(digest8_t digest) { - digest32_t d32; - finalize(d32); - size_t di = 0; - digest[di++] = ((d32[0] >> 24) & 0xFF); - digest[di++] = ((d32[0] >> 16) & 0xFF); - digest[di++] = ((d32[0] >> 8) & 0xFF); - digest[di++] = ((d32[0]) & 0xFF); - - digest[di++] = ((d32[1] >> 24) & 0xFF); - digest[di++] = ((d32[1] >> 16) & 0xFF); - digest[di++] = ((d32[1] >> 8) & 0xFF); - digest[di++] = ((d32[1]) & 0xFF); - - digest[di++] = ((d32[2] >> 24) & 0xFF); - digest[di++] = ((d32[2] >> 16) & 0xFF); - digest[di++] = ((d32[2] >> 8) & 0xFF); - digest[di++] = ((d32[2]) & 0xFF); - - digest[di++] = ((d32[3] >> 24) & 0xFF); - digest[di++] = ((d32[3] >> 16) & 0xFF); - digest[di++] = ((d32[3] >> 8) & 0xFF); - digest[di++] = ((d32[3]) & 0xFF); - - digest[di++] = ((d32[4] >> 24) & 0xFF); - digest[di++] = ((d32[4] >> 16) & 0xFF); - digest[di++] = ((d32[4] >> 8) & 0xFF); - digest[di++] = ((d32[4]) & 0xFF); - return digest; - } - - protected: - void processBlock() { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) { - w[i] = (m_block[i * 4 + 0] << 24); - w[i] |= (m_block[i * 4 + 1] << 16); - w[i] |= (m_block[i * 4 + 2] << 8); - w[i] |= (m_block[i * 4 + 3]); - } - for (size_t i = 16; i < 80; i++) { - w[i] = LeftRotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); - } - - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; - - for (std::size_t i = 0; i < 80; ++i) { - uint32_t f = 0; - uint32_t k = 0; - - if (i < 20) { - f = (b & c) | (~b & d); - k = 0x5A827999; - } else if (i < 40) { - f = b ^ c ^ d; - k = 0x6ED9EBA1; - } else if (i < 60) { - f = (b & c) | (b & d) | (c & d); - k = 0x8F1BBCDC; - } else { - f = b ^ c ^ d; - k = 0xCA62C1D6; - } - uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i]; - e = d; - d = c; - c = LeftRotate(b, 30); - b = a; - a = temp; - } - - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; - } - - private: - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; -}; -} -#endif diff --git a/thirdparty/libmspack b/thirdparty/libmspack deleted file mode 160000 index 3059077..0000000 --- a/thirdparty/libmspack +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 305907723a4e7ab2018e58040059ffb5e77db837 diff --git a/thirdparty/tiny-AES-c b/thirdparty/tiny-AES-c deleted file mode 160000 index 2385675..0000000 --- a/thirdparty/tiny-AES-c +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 23856752fbd139da0b8ca6e471a13d5bcc99a08d diff --git a/tools/XenonRecomp b/tools/XenonRecomp index 0fc545a..cd6fcb3 160000 --- a/tools/XenonRecomp +++ b/tools/XenonRecomp @@ -1 +1 @@ -Subproject commit 0fc545a6e25275d3a4c79685d32d2eb22fe98e98 +Subproject commit cd6fcb33bdcaff37c8c9d2083c7951e1d73ae9da