bool FEncryptXorCopyFile(FILE* a_fpDest, FILE* a_fpSrc, const char* a_pXorFileName, n64 a_nOffset, n64 a_nSize, bool a_bVerbose) { FILE* fpXor = FFopen(a_pXorFileName, "rb"); if (fpXor == nullptr) { return false; } FFseek(fpXor, 0, SEEK_END); n64 nXorSize = FFtell(fpXor); if (nXorSize < a_nSize && a_bVerbose) { fclose(fpXor); printf("ERROR: xor file %s size less than data size\n\n", a_pXorFileName); return false; } FFseek(fpXor, 0, SEEK_SET); const n64 nBufferSize = 0x100000; u8* pDataBuffer = new u8[nBufferSize]; u8* pXorBuffer = new u8[nBufferSize]; FFseek(a_fpSrc, a_nOffset, SEEK_SET); while (a_nSize > 0) { n64 nSize = a_nSize > nBufferSize ? nBufferSize : a_nSize; fread(pDataBuffer, 1, static_cast<size_t>(nSize), a_fpSrc); fread(pXorBuffer, 1, static_cast<size_t>(nSize), fpXor); u64* pDataBuffer64 = reinterpret_cast<u64*>(pDataBuffer); u64* pXorBuffer64 = reinterpret_cast<u64*>(pXorBuffer); n64 nXorCount = FAlign(nSize, 8) / 8; for (n64 i = 0; i < nXorCount; i++) { *pDataBuffer64++ ^= *pXorBuffer64++; } fwrite(pDataBuffer, 1, static_cast<size_t>(nSize), a_fpDest); a_nSize -= nSize; } delete[] pXorBuffer; delete[] pDataBuffer; fclose(fpXor); return true; }
bool FEncryptXorFile(const char* a_pDataFileName, const char* a_pXorFileName, n64 a_nDataOffset, n64 a_nDataSize, bool a_bDataFileAll, n64 a_nXorOffset, bool a_bVerbose) { FILE* fpData = FFopen(a_pDataFileName, "rb+"); if (fpData == nullptr) { return false; } FFseek(fpData, 0, SEEK_END); n64 nDataSize = FFtell(fpData); if (nDataSize < a_nDataOffset) { fclose(fpData); printf("ERROR: data file %s size less than data offset\n\n", a_pDataFileName); return false; } if (a_bDataFileAll) { a_nDataSize = nDataSize - a_nDataOffset; } if (nDataSize < a_nDataOffset + a_nDataSize) { if (a_bVerbose) { fclose(fpData); printf("ERROR: data file %s size less than data offset + data size\n\n", a_pDataFileName); return false; } a_nDataSize = nDataSize - a_nDataOffset; } FILE* fpXor = FFopen(a_pXorFileName, "rb"); if (fpXor == nullptr) { fclose(fpData); return false; } FFseek(fpXor, 0, SEEK_END); n64 nXorSize = FFtell(fpXor); if (nXorSize - a_nXorOffset < a_nDataSize) { if (a_bVerbose) { fclose(fpXor); fclose(fpData); printf("ERROR: xor file %s size less than data size\n\n", a_pXorFileName); return false; } a_nDataSize = nXorSize - a_nXorOffset; } FFseek(fpXor, a_nXorOffset, SEEK_SET); n64 nIndex = 0; const n64 nBufferSize = 0x100000; u8* pDataBuffer = new u8[nBufferSize]; u8* pXorBuffer = new u8[nBufferSize]; while (a_nDataSize > 0) { n64 nSize = a_nDataSize > nBufferSize ? nBufferSize : a_nDataSize; FFseek(fpData, a_nDataOffset + nIndex * nBufferSize, SEEK_SET); fread(pDataBuffer, 1, static_cast<size_t>(nSize), fpData); fread(pXorBuffer, 1, static_cast<size_t>(nSize), fpXor); u64* pDataBuffer64 = reinterpret_cast<u64*>(pDataBuffer); u64* pXorBuffer64 = reinterpret_cast<u64*>(pXorBuffer); n64 nXorCount = FAlign(nSize, 8) / 8; for (n64 i = 0; i < nXorCount; i++) { *pDataBuffer64++ ^= *pXorBuffer64++; } FFseek(fpData, a_nDataOffset + nIndex * nBufferSize, SEEK_SET); fwrite(pDataBuffer, 1, static_cast<size_t>(nSize), fpData); a_nDataSize -= nSize; nIndex++; } delete[] pXorBuffer; delete[] pDataBuffer; fclose(fpXor); fclose(fpData); return true; }
void* FMallocBinned::realloc(void* origin, size_t newSize, uint32_t alignment) { // Handle DefaultAlignment for binned allocator. if (alignment == DefaultAlignment) { alignment = default_binned_allocator_alignment; } FAssert(alignment <= pageSize); alignment = std::max<uint32_t>(alignment, default_binned_allocator_alignment); if (newSize) { newSize = std::max<size_t>(alignment, FAlign(newSize, alignment)); } MEM_TIME(MemTime -= FPlatformTime::Seconds()); UIntPtr_t basePtr; void* newPtr = origin; if( origin && newSize ) { FPoolInfo* pool = findPoolInfo((UIntPtr_t)origin, basePtr); if( pool->tableIndex < binnedOSTableIndex ) { // Allocated from pool, so grow or shrink if necessary. FAssert(pool->tableIndex > 0); // it isn't possible to allocate a size of 0, Malloc will increase the size to default_binned_allocator_alignment const uint32_t thisTableBlockSize = memSizeToPoolTable[pool->tableIndex]->blockSize; if( newSize > thisTableBlockSize || newSize <= memSizeToPoolTable[pool->tableIndex - 1]->blockSize ) { newPtr = this->malloc( newSize, alignment ); FMemory::memcpy( newPtr, origin, std::min<size_t>( newSize, thisTableBlockSize ) ); this->free( origin ); } } else { // Allocated from OS. FAssert(!((UIntPtr_t)origin & (pageSize-1))); if( newSize > pool->getOsBytes(pageSize, (int32_t)binnedOSTableIndex) || newSize * 3 < pool->getOsBytes(pageSize, (uint32_t)binnedOSTableIndex) * 2 ) { // Grow or shrink. newPtr = this->malloc( newSize, alignment ); FMemory::memcpy( newPtr, origin, std::min<size_t>(newSize, pool->getBytes()) ); this->free( origin ); } else { // Keep as-is, reallocation isn't worth the overhead. STAT(usedCurrent += newSize - pool->getBytes()); STAT(usedPeak = std::max(usedPeak, usedCurrent)); STAT(wasteCurrent += pool->getBytes() - newSize); pool->setAllocationSizes((uint32_t)newSize, pool->getOsBytes(pageSize, (uint32_t)binnedOSTableIndex), (uint32_t)binnedOSTableIndex, (uint32_t)binnedOSTableIndex); } } } else if( origin == nullptr ) { newPtr = this->malloc( newSize, alignment ); } else { this->free( origin ); newPtr = nullptr; } MEM_TIME(MemTime += FPlatformTime::Seconds()); return newPtr; }
void* FMallocBinned::malloc(size_t size, uint32_t alignment) { #ifdef USE_COARSE_GRAIN_LOCKS FScopeLock ScopedLock(&AccessGuard); #endif flushPendingFrees(); // Handle DEFAULT_ALIGNMENT for binned allocator. if (alignment == DefaultAlignment) { alignment = default_binned_allocator_alignment; } FAssert(alignment <= pageSize); alignment = std::max<uint32_t>(alignment, default_binned_allocator_alignment); size = std::max<size_t>(alignment, FAlign(size, alignment)); MEM_TIME(MemTime -= FPlatformTime::Seconds()); STAT(currentAllocs++); STAT(totalAllocs++); FFreeMem* free = nullptr; if( size < binnedSizeLimit ) { // Allocate from pool. FPoolTable* table = memSizeToPoolTable[size]; #ifdef USE_FINE_GRAIN_LOCKS std::lock_guard<std::mutex> tableLock(table->mutex); #endif FAssert(size <= table->blockSize); trackStats(table, (uint32_t)size); FPoolInfo* pool = table->firstPool; if( !pool ) { pool = allocatePoolMemory(table, binned_alloc_pool_size/*PageSize*/, size); } free = allocateBlockFromPool(table, pool); } else if ( ((size >= binnedSizeLimit && size <= pagePoolTable[0].blockSize) || (size > pageSize && size <= pagePoolTable[1].blockSize)) && alignment == default_binned_allocator_alignment ) { // Bucket in a pool of 3*PageSize or 6*PageSize uint32_t binType = size < pageSize ? 0 : 1; uint32_t pageCount = 3 * binType + 3; FPoolTable* table = &pagePoolTable[binType]; #ifdef USE_FINE_GRAIN_LOCKS std::lock_guard<std::mutex> tableLock(table->mutex); #endif FAssert(size <= table->blockSize); trackStats(table, (uint32_t)size); FPoolInfo* pool = table->firstPool; if( !pool ) { pool = allocatePoolMemory(table, pageCount * pageSize, binnedSizeLimit + binType); } free = allocateBlockFromPool(table, pool); } else { // Use OS for large allocations. UIntPtr_t alignedSize = FAlign(size, pageSize); size_t actualPoolSize; //TODO: use this to reduce waste? free = (FFreeMem*)osAlloc(alignedSize, actualPoolSize); if( !free ) { outOfMemory(alignedSize); } FAssert(!((size_t)free & (pageSize - 1))); // Create indirect. FPoolInfo* pool; { #ifdef USE_FINE_GRAIN_LOCKS std::lock_guard<std::mutex> poolInfoLock(accessGuard); #endif pool = getPoolInfo((UIntPtr_t)free); } pool->setAllocationSizes((uint32_t)size, alignedSize, (uint32_t)binnedOSTableIndex, (uint32_t)binnedOSTableIndex); STAT(osPeak = std::max(osPeak, osCurrent += alignedSize)); STAT(usedPeak = std::max(usedPeak, usedCurrent += size)); STAT(wastePeak = std::max(wastePeak, wasteCurrent += alignedSize - size)); } MEM_TIME(MemTime += FPlatformTime::Seconds()); return free; }