2024-04-05 17:51:19 +02:00
//=============================================================================//
//
// Purpose: pak file loading and unloading
//
//=============================================================================//
# include "rtech/ipakfile.h"
# include "rtech/async/asyncio.h"
# include "paktools.h"
# include "pakstate.h"
# include "pakpatch.h"
# include "pakalloc.h"
# include "pakparse.h"
# include "pakdecode.h"
# include "pakstream.h"
//-----------------------------------------------------------------------------
// resolve the target guid from lookuo table
//-----------------------------------------------------------------------------
static bool Pak_ResolveAssetDependency ( const PakFile_t * const pak , PakGuid_t currentGuid ,
const PakGuid_t targetGuid , int & currentIndex , const bool shouldCheckTwo )
{
while ( true )
{
if ( shouldCheckTwo & & currentGuid = = 2 )
{
if ( pak - > memoryData . pakHeader . assetCount )
return false ;
}
currentIndex + + ;
if ( currentIndex > = PAK_MAX_ASSETS )
return false ;
currentIndex & = PAK_MAX_ASSETS_MASK ;
currentGuid = g_pPakGlobals - > m_assets [ currentIndex ] . guid ;
if ( currentGuid = = targetGuid )
return true ;
}
UNREACHABLE ( ) ;
}
//-----------------------------------------------------------------------------
// resolve guid relations for asset
//-----------------------------------------------------------------------------
void Pak_ResolveAssetRelations ( PakFile_t * const pak , const PakAsset_t * const asset )
{
PakPage_t * const pGuidDescriptors = & pak - > memoryData . guidDescriptors [ asset - > dependenciesIndex ] ;
volatile uint32_t * v5 = reinterpret_cast < volatile uint32_t * > ( * ( reinterpret_cast < uint64_t * > ( g_pPakGlobals ) + 0x17 * ( pak - > memoryData . pakId & PAK_MAX_HANDLES_MASK ) + 0x160212 ) ) ;
if ( pak_debugrelations - > GetBool ( ) )
Msg ( eDLL_T : : RTECH , " Resolving relations for asset: '0x%-16llX', dependencies: %-4u; in pak '%s' \n " ,
asset - > guid , asset - > dependenciesCount , pak - > memoryData . fileName ) ;
for ( uint32_t i = 0 ; i < asset - > dependenciesCount ; i + + )
{
void * * const pCurrentGuid = reinterpret_cast < void * * > ( pak - > memoryData . memPageBuffers [ pGuidDescriptors [ i ] . index ] + pGuidDescriptors [ i ] . offset ) ;
// get current guid
const PakGuid_t targetGuid = reinterpret_cast < uint64_t > ( * pCurrentGuid ) ;
// get asset index
int currentIndex = targetGuid & PAK_MAX_ASSETS_MASK ;
const PakGuid_t currentGuid = g_pPakGlobals - > m_assets [ currentIndex ] . guid ;
const int64_t v9 = 2 i64 * InterlockedExchangeAdd ( v5 , 1u ) ;
* reinterpret_cast < PakGuid_t * > ( const_cast < uint32_t * > ( & v5 [ 2 * v9 + 2 ] ) ) = targetGuid ;
* reinterpret_cast < PakGuid_t * > ( const_cast < uint32_t * > ( & v5 [ 2 * v9 + 4 ] ) ) = asset - > guid ;
if ( currentGuid ! = targetGuid )
{
// are we some special asset with the guid 2?
if ( ! Pak_ResolveAssetDependency ( pak , currentGuid , targetGuid , currentIndex , true ) )
{
PakAsset_t * assetEntries = pak - > memoryData . assetEntries ;
uint64_t a = 0 ;
for ( ; assetEntries - > guid ! = targetGuid ; a + + , assetEntries + + )
{
if ( a > = pak - > memoryData . pakHeader . assetCount )
{
if ( ! Pak_ResolveAssetDependency ( pak , currentGuid , targetGuid , currentIndex , false ) )
{
// the dependency couldn't be resolved, this state is irrecoverable;
// error out
Error ( eDLL_T : : RTECH , EXIT_FAILURE , " Failed to resolve asset dependency %u of %u \n "
" pak: '%s' \n "
" asset: '0x%llX' \n "
2024-01-27 01:45:57 +01:00
" target: '0x%llX' \n " ,
2024-04-05 17:51:19 +02:00
i , asset - > dependenciesCount ,
pak - > memoryData . fileName ,
asset - > guid ,
2024-01-27 01:45:57 +01:00
targetGuid ) ;
2024-04-05 17:51:19 +02:00
}
break ;
}
}
currentIndex = pak - > memoryData . qword2E0 [ a ] ;
}
}
// finally write the pointer to the guid entry
* pCurrentGuid = g_pPakGlobals - > m_assets [ currentIndex ] . m_head ;
}
}
uint32_t Pak_ProcessRemainingPagePointers ( PakFile_t * const pak )
{
uint32_t processedPointers = 0 ;
for ( processedPointers = pak - > numProcessedPointers ; processedPointers < pak - > GetPointerCount ( ) ; + + processedPointers )
{
PakPage_t * const curPage = & pak - > memoryData . virtualPointers [ processedPointers ] ;
int curCount = curPage - > index - pak - > firstPageIdx ;
if ( curCount < 0 )
curCount + = pak - > memoryData . pakHeader . memPageCount ;
if ( curCount > = pak - > processedPageCount )
break ;
PakPage_t * const ptr = reinterpret_cast < PakPage_t * > ( pak - > GetPointerForPageOffset ( curPage ) ) ;
ptr - > ptr = pak - > memoryData . memPageBuffers [ ptr - > index ] + ptr - > offset ;
}
return processedPointers ;
}
void __fastcall Rebuild_14043E030 ( PakFile_t * const pak )
{
__int64 numAssets ; // rsi
PakAsset_t * pakAsset ; // rdi
__int64 _numAssets ; // r14
unsigned int assetBind ; // ebp
__int64 v13 ; // rcx
__int64 qword2D8_low ; // rdi
JobID_t qword2D8_high ; // ebp
JobTypeID_t v16 ; // si
pak - > numProcessedPointers = Pak_ProcessRemainingPagePointers ( pak ) ;
numAssets = ( unsigned int ) pak - > processedAssetCount ;
if ( ( _DWORD ) numAssets ! = pak - > memoryData . pakHeader . assetCount )
{
pakAsset = & pak - > memoryData . assetEntries [ numAssets ] ;
_numAssets = ( unsigned int ) numAssets ;
if ( ( int ) pakAsset - > pageEnd < = pak - > processedPageCount )
{
while ( ( unsigned __int16 ) * word_167ED7BDE < = 0xC8u )
{
assetBind = pakAsset - > HashTableIndexForAssetType ( ) ;
pak - > memoryData . qword2E0 [ _numAssets ] = ( int ) sub_14043D3C0 ( pak , pakAsset ) ;
_InterlockedIncrement16 ( word_167ED7BDE ) ;
v13 = assetBind ;
if ( g_pPakGlobals - > m_assetBindings [ ( unsigned __int64 ) assetBind ] . loadAssetFunc )
{
qword2D8_low = pak - > memoryData . pakId ;
qword2D8_high = pak - > memoryData . unkJobID ;
v16 = * ( ( _BYTE * ) & * g_pPakGlobals + v13 + 13207872 ) ;
JTGuts_AddJob ( v16 , qword2D8_high , ( void * ) qword2D8_low , ( void * ) _numAssets ) ;
}
else
{
if ( _InterlockedExchangeAdd16 ( ( volatile signed __int16 * ) & pakAsset - > numRemainingDependencies , 0xFFFFu ) = = 1 )
sub_14043D150 ( pak , pakAsset , ( unsigned int ) numAssets , assetBind ) ;
_InterlockedDecrement16 ( word_167ED7BDE ) ;
}
numAssets = ( unsigned int ) + + pak - > processedAssetCount ;
if ( ( _DWORD ) numAssets = = pak - > memoryData . pakHeader . assetCount )
{
JT_EndJobGroup ( pak - > memoryData . unkJobID ) ;
return ;
}
_numAssets = ( unsigned int ) numAssets ;
pakAsset = & pak - > memoryData . assetEntries [ numAssets ] ;
if ( pakAsset - > pageEnd > pak - > processedPageCount )
return ;
}
}
}
}
//-----------------------------------------------------------------------------
// load user-requested pak files on-demand
//-----------------------------------------------------------------------------
PakHandle_t Pak_LoadAsync ( const char * const fileName , CAlignedMemAlloc * const allocator , const int nIdx , const bool bUnk )
{
PakHandle_t pakId = INVALID_PAK_HANDLE ;
if ( Pak_FileExists ( fileName ) )
{
Msg ( eDLL_T : : RTECH , " Loading pak file: '%s' \n " , fileName ) ;
pakId = v_Pak_LoadAsync ( fileName , allocator , nIdx , bUnk ) ;
if ( pakId = = INVALID_PAK_HANDLE )
Error ( eDLL_T : : RTECH , NO_ERROR , " %s: Failed read '%s' results '%d' \n " , __FUNCTION__ , fileName , pakId ) ;
}
else
{
Error ( eDLL_T : : RTECH , NO_ERROR , " %s: Failed; file '%s' doesn't exist \n " , __FUNCTION__ , fileName ) ;
}
return pakId ;
}
//-----------------------------------------------------------------------------
// unloads loaded pak files
//-----------------------------------------------------------------------------
void Pak_UnloadAsync ( PakHandle_t handle )
{
const PakLoadedInfo_t * const pakInfo = Pak_GetPakInfo ( handle ) ;
if ( pakInfo & & pakInfo - > fileName )
Msg ( eDLL_T : : RTECH , " Unloading pak file: '%s' \n " , pakInfo - > fileName ) ;
v_Pak_UnloadAsync ( handle ) ;
}
# define CMD_INVALID -1
// only patch cmds 4,5,6 use this array to determine their data size
static const int s_patchCmdToBytesToProcess [ ] = { CMD_INVALID , CMD_INVALID , CMD_INVALID , CMD_INVALID , 3 , 7 , 6 , 0 } ;
# undef CMD_INVALID
//----------------------------------------------------------------------------------
// loads and processes a pak file (handles decompression and patching)
// TODO: !!! FINISH REBUILD !!!
//----------------------------------------------------------------------------------
bool Pak_ProcessPakFile ( PakFile_t * const pak )
{
PakFileHeader_t * pakHeader ; // r8
PakFileStream_t * fileStream ; // rsi
PakMemoryData_t * memoryData ; // r14
__int64 dwordB8 ; // rcx
unsigned int v6 ; // eax // [was: int]
__int64 v7 ; // rax
char v8 ; // r13
//signed __int64 index_Maybe; // rdi
//char v10; // r15
//__int64 v11; // rdx
//const char* v12; // rbp
size_t bytesProcessed ; // eax
char byteBF ; // al
unsigned __int64 v16 ; // r9
unsigned __int8 v17 ; // cl
unsigned __int64 v18 ; // r8
uint8_t byte1F8 ; // al
uint8_t byte1FD ; // cl
PakFileStream_t : : Descriptor * v22 ; // rdi
size_t dataOffset ; // rax
PakDecoder_t * decodeContext ; // rbp
size_t decompressedSize ; // rax
size_t compressedSize ; // rdx
uint64_t qword1D0 ; // rcx
__int64 v28 ; // rax
unsigned int numBitsRemaining ; // r8d
int v35 ; // ecx
int v39 ; // r10d
int v40 ; // r9d
unsigned int v42 ; // ecx
unsigned int v43 ; // r8d
unsigned int v44 ; // r12d
char byteBC ; // r15
__int64 v46 ; // rbp
__int64 v47 ; // r8
unsigned __int64 v48 ; // rbp
unsigned __int64 qword8 ; // rax
__int64 v50 ; // rdi
char c ; // al
char * it ; // rcx
char * i ; // rdx
int v56 ; // edi
unsigned int patchCount ; // r15
unsigned __int64 v58 ; // rdx
char pakPatchPath [ MAX_PATH ] ; // [rsp+40h] [rbp-148h] BYREF
unsigned __int64 v62 ; // [rsp+190h] [rbp+8h]
size_t numBytesToProcess ; // [rsp+198h] [rbp+10h] BYREF
fileStream = & pak - > fileStream ;
memoryData = & pak - > memoryData ;
dwordB8 = ( unsigned int ) pak - > fileStream . dwordB8 ;
if ( ( _DWORD ) dwordB8 )
v62 = dwordB8 < < 19 ;
else
v62 = sizeof ( PakFileHeader_t ) ;
v6 = fileStream - > unsigned_intB4 ;
if ( v6 ! = ( _DWORD ) dwordB8 )
{
while ( 1 )
{
v7 = v6 & 0x1F ;
v8 = fileStream - > gap94 [ v7 ] ;
if ( v8 ! = 1 )
break ;
LABEL_17 :
v6 = fileStream - > unsigned_intB4 + 1 ;
fileStream - > unsigned_intB4 = v6 ;
if ( v6 = = fileStream - > dwordB8 )
goto LABEL_18 ;
}
const char * statusMsg = " (no reason) " ;
const uint8_t currentStatus = g_pakLoadApi - > CheckAsyncRequest ( ( unsigned char ) fileStream - > gap14 [ v7 ] , & bytesProcessed , & statusMsg ) ;
if ( currentStatus = = AsyncHandleStatus_t : : FS_ASYNC_PENDING )
goto LABEL_18 ;
if ( currentStatus = = AsyncHandleStatus_t : : FS_ASYNC_ERROR )
Error ( eDLL_T : : RTECH , EXIT_FAILURE , " Error reading pak file \" %s \" -- %s \n " , pak - > memoryData . fileName , statusMsg ) ;
2024-01-27 01:45:57 +01:00
fileStream - > bytesStreamed + = bytesProcessed ;
2024-04-05 17:51:19 +02:00
if ( v8 )
{
byteBF = fileStream - > byteBF + + ;
pakHeader = & pak - > memoryData . pakHeader ;
v16 = ( unsigned __int64 ) fileStream - > unsigned_intB4 < < 19 ;
if ( v8 = = 2 )
{
v18 = v16 & fileStream - > qword1C8 ;
2024-01-27 01:45:57 +01:00
fileStream - > bytesStreamed = bytesProcessed + v16 ;
2024-04-05 17:51:19 +02:00
pakHeader = ( PakFileHeader_t * ) & fileStream - > buffer [ v18 ] ;
}
v17 = byteBF & 7 ;
fileStream - > m_descriptors [ v17 ] . dataOffset = v16 + sizeof ( PakFileHeader_t ) ;
fileStream - > m_descriptors [ v17 ] . compressedSize = v16 + pakHeader - > compressedSize ;
fileStream - > m_descriptors [ v17 ] . decompressedSize = pakHeader - > decompressedSize ;
2024-01-24 23:49:30 +01:00
fileStream - > m_descriptors [ v17 ] . isCompressed = pakHeader - > IsCompressed ( ) ;
2024-04-05 17:51:19 +02:00
}
goto LABEL_17 ;
}
LABEL_18 :
byte1F8 = pak - > byte1F8 ;
if ( byte1F8 ! = fileStream - > byteBF )
{
2024-01-27 01:45:57 +01:00
const bool useZStream = pak - > GetHeader ( ) . flags & PAK_HEADER_FLAGS_ZSTREAM ;
2024-01-24 23:49:30 +01:00
2024-04-05 17:51:19 +02:00
byte1FD = pak - > byte1FD ;
do
{
v22 = & fileStream - > m_descriptors [ byte1F8 & 7 ] ;
if ( byte1FD )
{
pak - > byte1FD = 0 ;
pak - > inputBytePos = v22 - > dataOffset ;
if ( v22 - > isCompressed )
{
pak - > isOffsetted_MAYBE = 0 ;
pak - > isCompressed = 1 ;
dataOffset = sizeof ( PakFileHeader_t ) ;
}
else
{
pak - > isOffsetted_MAYBE = 1 ;
pak - > isCompressed = 0 ;
dataOffset = v22 - > dataOffset ;
}
memoryData - > processedPatchedDataSize = dataOffset ;
if ( ! pak - > isCompressed )
{
LABEL_35 :
compressedSize = v22 - > compressedSize ;
qword1D0 = compressedSize ;
2024-01-27 01:45:57 +01:00
if ( fileStream - > bytesStreamed < compressedSize )
qword1D0 = fileStream - > bytesStreamed ;
2024-04-05 17:51:19 +02:00
goto LABEL_41 ;
}
decodeContext = & pak - > pakDecoder ;
2024-01-28 01:57:11 +01:00
decompressedSize = Pak_InitDecoder ( & pak - > pakDecoder ,
fileStream - > buffer , pak - > decompBuffer ,
PAK_DECODE_IN_RING_BUFFER_MASK , PAK_DECODE_OUT_RING_BUFFER_MASK ,
v22 - > compressedSize - ( v22 - > dataOffset - sizeof ( PakFileHeader_t ) ) ,
2024-01-27 01:45:57 +01:00
v22 - > dataOffset - sizeof ( PakFileHeader_t ) , sizeof ( PakFileHeader_t ) , useZStream ) ;
2024-04-05 17:51:19 +02:00
if ( decompressedSize ! = v22 - > decompressedSize )
Error ( eDLL_T : : RTECH , EXIT_FAILURE ,
" Error reading pak file \" %s \" -- decompressed size %zu doesn't match expected value %zu \n " ,
pak - > memoryData . fileName ,
2024-01-24 23:51:39 +01:00
decompressedSize ,
2024-04-05 17:51:19 +02:00
pak - > memoryData . pakHeader . decompressedSize ) ;
}
else
{
decodeContext = & pak - > pakDecoder ;
}
if ( ! pak - > isCompressed )
goto LABEL_35 ;
qword1D0 = pak - > pakDecoder . outBufBytePos ;
if ( qword1D0 ! = pak - > pakDecoder . decompSize )
{
2024-01-27 01:45:57 +01:00
const bool didDecode = Pak_StreamToBufferDecode ( decodeContext , fileStream - > bytesStreamed , memoryData - > processedPatchedDataSize + PAK_DECODE_OUT_RING_BUFFER_SIZE , useZStream ) ;
2024-01-24 23:49:30 +01:00
2024-04-05 17:51:19 +02:00
qword1D0 = pak - > pakDecoder . outBufBytePos ;
pak - > inputBytePos = pak - > pakDecoder . inBufBytePos ;
2024-01-24 23:49:30 +01:00
2024-01-27 01:45:57 +01:00
if ( didDecode )
DevMsg ( eDLL_T : : RTECH , " %s: pak '%s' decoded successfully \n " , __FUNCTION__ , pak - > GetName ( ) ) ;
2024-04-05 17:51:19 +02:00
}
2024-01-24 23:49:30 +01:00
2024-04-05 17:51:19 +02:00
compressedSize = v22 - > compressedSize ;
LABEL_41 :
if ( pak - > inputBytePos ! = compressedSize | | memoryData - > processedPatchedDataSize ! = qword1D0 )
goto LABEL_45 ;
byte1FD = 1 ;
byte1F8 = pak - > byte1F8 + 1 ;
pak - > byte1FD = 1 ;
pak - > byte1F8 = byte1F8 ;
} while ( byte1F8 ! = fileStream - > byteBF ) ;
}
qword1D0 = memoryData - > processedPatchedDataSize ;
LABEL_45 :
v28 = memoryData - > field_2A8 ;
numBytesToProcess = qword1D0 - memoryData - > processedPatchedDataSize ;
if ( memoryData - > patchSrcSize + v28 )
{
do
{
// if there are no bytes left to process in this patch operation
if ( ! memoryData - > numBytesToProcess_maybe )
{
RBitRead & bitbuf = memoryData - > bitBuf ;
numBitsRemaining = bitbuf . m_bitsRemaining ; // number of "free" bits in the bitbuf (how many to fetch)
// fetch remaining bits
bitbuf . m_dataBuf | = * ( _QWORD * ) memoryData - > patchData < < ( 64 - ( unsigned __int8 ) numBitsRemaining ) ;
// advance patch data buffer by the number of bytes that have just been fetched
memoryData - > patchData = & memoryData - > patchData [ numBitsRemaining > > 3 ] ;
// store the number of bits remaining to complete the data read
bitbuf . m_bitsRemaining = numBitsRemaining & 7 ; // number of bits above a whole byte
const unsigned __int8 index1 = static_cast < unsigned __int8 > ( bitbuf . ReadBits ( 6 ) ) ;
v35 = memoryData - > PATCH_field_68 [ index1 ] ; // number of bits to discard from bitbuf
__int8 cmd = memoryData - > patchCommands [ index1 ] ;
bitbuf . DiscardBits ( v35 ) ;
// get the next patch function to execute
memoryData - > patchFunc = g_pakPatchApi [ cmd ] ;
if ( cmd < = 3u )
{
const unsigned __int8 index2 = static_cast < unsigned __int8 > ( bitbuf . ReadBits ( 8 ) ) ;
v39 = memoryData - > PATCH_unk3 [ index2 ] ;
v40 = memoryData - > PATCH_unk2 [ index2 ] ; // number of stored bits for the data size
bitbuf . DiscardBits ( v39 ) ;
memoryData - > numBytesToProcess_maybe = ( 1ull < < v40 ) + bitbuf . ReadBits ( v40 ) ;
bitbuf . DiscardBits ( v40 ) ;
}
else
{
memoryData - > numBytesToProcess_maybe = s_patchCmdToBytesToProcess [ cmd ] ;
}
}
} while ( pak - > memoryData . patchFunc ( pak , & numBytesToProcess ) & & memoryData - > patchSrcSize + memoryData - > field_2A8 ) ;
}
if ( pak - > isOffsetted_MAYBE )
pak - > inputBytePos = memoryData - > processedPatchedDataSize ;
if ( ! fileStream - > finishedLoadingPatches )
{
v42 = fileStream - > unsigned_intB4 ;
v43 = fileStream - > dwordB8 ;
if ( ( unsigned int ) ( pak - > inputBytePos > > 19 ) < v42 )
v42 = ( unsigned int ) pak - > inputBytePos > > 19 ; // New cast added
v44 = v42 + 32 ;
if ( v43 ! = v42 + 32 )
{
while ( 1 )
{
byteBC = fileStream - > byteBC ;
v46 = v43 ;
v47 = v43 & 0x1F ;
v48 = ( v46 + 1 ) < < 19 ;
if ( byteBC = = 1 )
break ;
qword8 = fileStream - > qword8 ;
if ( v62 < qword8 )
{
v50 = ( unsigned int ) v47 ;
if ( v48 < qword8 )
qword8 = v48 ;
fileStream - > gap14 [ ( unsigned int ) v47 ] = v_FS_ReadAsyncFile (
fileStream - > fileHandle ,
v62 - fileStream - > qword0 ,
qword8 - v62 ,
& fileStream - > buffer [ v62 & fileStream - > qword1C8 ] ,
0 i64 ,
0 i64 ,
4 ) ;
fileStream - > gap94 [ v50 ] = byteBC ;
fileStream - > byteBC = 0 ;
goto LABEL_65 ;
}
if ( pak - > patchCount > = pak - > memoryData . pakHeader . patchIndex )
{
FS_CloseAsyncFile ( ( short ) fileStream - > fileHandle ) ;
fileStream - > fileHandle = INVALID_PAK_HANDLE ;
fileStream - > qword0 = 0 i64 ;
fileStream - > finishedLoadingPatches = true ;
return memoryData - > patchSrcSize = = 0 ;
}
if ( ! pak - > dword14 )
return memoryData - > patchSrcSize = = 0 ;
sprintf ( pakPatchPath , PLATFORM_PAK_PATH " %s " , pak - > memoryData . fileName ) ;
patchCount = pak - > patchCount + + ;
// get path of next patch rpak to load
if ( pak - > memoryData . patchIndices [ patchCount ] )
{
c = pakPatchPath [ 0 ] ;
it = pakPatchPath ;
for ( i = nullptr ; c ; + + it )
{
if ( c = = ' . ' )
{
i = it ;
}
else if ( c = = ' \\ ' | | c = = ' / ' )
{
i = nullptr ;
}
c = it [ 1 ] ;
}
if ( i )
it = i ;
// replace extension '.rpak' with '(xx).rpak'
snprintf ( it , & pakPatchPath [ sizeof ( pakPatchPath ) ] - it ,
" (%02u).rpak " , pak - > memoryData . patchIndices [ patchCount ] ) ;
}
v56 = FS_OpenAsyncFile ( pakPatchPath , 5 i64 , & numBytesToProcess ) ;
if ( v56 = = FS_ASYNC_FILE_INVALID )
Error ( eDLL_T : : RTECH , EXIT_FAILURE , " Couldn't open file \" %s \" . \n " , pakPatchPath ) ;
if ( numBytesToProcess < pak - > memoryData . patchHeaders [ patchCount ] . m_sizeDisk )
Error ( eDLL_T : : RTECH , EXIT_FAILURE , " File \" %s \" appears truncated; read size: %zu < expected size: %zu. \n " ,
pakPatchPath , numBytesToProcess , pak - > memoryData . patchHeaders [ patchCount ] . m_sizeDisk ) ;
FS_CloseAsyncFile ( ( short ) fileStream - > fileHandle ) ;
v43 = fileStream - > dwordB8 ;
fileStream - > fileHandle = v56 ;
v58 = ( unsigned __int64 ) ( ( v43 + 7 ) & 0xFFFFFFF8 ) < < 19 ;
fileStream - > qword0 = v58 ;
fileStream - > byteBC = ( v43 = = ( ( v43 + 7 ) & 0xFFFFFFF8 ) ) + 1 ;
fileStream - > qword8 = v58 + pak - > memoryData . patchHeaders [ patchCount ] . m_sizeDisk ;
LABEL_84 :
if ( v43 = = v44 )
return memoryData - > patchSrcSize = = 0 ;
}
fileStream - > gap14 [ v47 ] = - 2 ;
fileStream - > gap94 [ v47 ] = 1 ;
if ( ( ( ( _BYTE ) v47 + 1 ) & 7 ) = = 0 )
fileStream - > byteBC = 2 ;
LABEL_65 :
v43 = + + fileStream - > dwordB8 ;
v62 = v48 ;
goto LABEL_84 ;
}
}
return memoryData - > patchSrcSize = = 0 ;
}
// sets patch variables for copying the next unprocessed page into the relevant segment buffer
// if this is a header page, fetch info from the next unprocessed asset and copy over the asset's header
bool SetupNextPageForPatching ( PakLoadedInfo_t * a1 , PakFile_t * pak )
{
Rebuild_14043E030 ( pak ) ;
// numProcessedPointers has just been set in the above function call
pak - > memoryData . numShiftedPointers = pak - > numProcessedPointers ;
if ( pak - > processedPageCount = = pak - > GetPageCount ( ) )
return false ;
//break;
const uint32_t highestProcessedPageIdx = pak - > processedPageCount + pak - > firstPageIdx ;
pak - > processedPageCount + + ;
int v26 = highestProcessedPageIdx - pak - > GetPageCount ( ) ;
if ( highestProcessedPageIdx < pak - > GetPageCount ( ) )
v26 = highestProcessedPageIdx ;
const PakPageHeader_t * const nextMemPageHeader = & pak - > memoryData . pageHeaders [ v26 ] ;
if ( ( pak - > memoryData . segmentHeaders [ nextMemPageHeader - > segmentIdx ] . typeFlags & ( SF_TEMP | SF_CPU ) ) ! = 0 )
{
pak - > memoryData . patchSrcSize = nextMemPageHeader - > dataSize ;
pak - > memoryData . patchDstPtr = reinterpret_cast < char * > ( pak - > memoryData . memPageBuffers [ v26 ] ) ;
return true ;
//continue;
}
// headers
PakAsset_t * pakAsset = pak - > memoryData . ppAssetEntries [ pak - > memoryData . someAssetCount ] ;
pak - > memoryData . patchSrcSize = pakAsset - > headerSize ;
int assetTypeIdx = pakAsset - > HashTableIndexForAssetType ( ) ;
pak - > memoryData . patchDstPtr = reinterpret_cast < char * > ( a1 - > segmentBuffers [ 0 ] ) + pak - > memoryData . unkAssetTypeBindingSizes [ assetTypeIdx ] ;
pak - > memoryData . unkAssetTypeBindingSizes [ assetTypeIdx ] + = g_pPakGlobals - > m_assetBindings [ assetTypeIdx ] . nativeClassSize ;
return true ;
}
bool Pak_ProcessAssets ( PakLoadedInfo_t * const a1 )
{
PakFile_t * const pak = a1 - > pakFile ;
while ( pak - > processedAssetCount ! = pak - > GetAssetCount ( ) )
{
// TODO: invert condition and make the branch encompass the whole loop
if ( ! ( pak - > memoryData . patchSrcSize + pak - > memoryData . field_2A8 ) )
{
const bool res = SetupNextPageForPatching ( a1 , pak ) ;
if ( res )
continue ;
else
break ;
}
if ( ! Pak_ProcessPakFile ( pak ) )
return false ;
// processedPageCount must be greater than 0 here otherwise the page index will be negative and cause a crash
// if this happens, something probably went wrong with the patch data condition at the start of the loop, as that
// function call should increment processedPageCount if it succeeded
assert ( pak - > processedPageCount > 0 ) ;
const uint32_t pageCount = pak - > GetPageCount ( ) ;
const uint32_t v4 = ( pak - > firstPageIdx - 1 ) + pak - > processedPageCount ;
uint32_t shiftedPageIndex = v4 ;
if ( v4 > = pageCount )
shiftedPageIndex - = pageCount ;
// if "temp_" segment
if ( ( pak - > memoryData . segmentHeaders [ pak - > memoryData . pageHeaders [ shiftedPageIndex ] . segmentIdx ] . typeFlags & ( SF_TEMP | SF_CPU ) ) ! = 0 )
{
const bool res = SetupNextPageForPatching ( a1 , pak ) ;
if ( res )
continue ;
else
break ;
}
PakAsset_t * asset = pak - > memoryData . ppAssetEntries [ pak - > memoryData . someAssetCount ] ;
const uint32_t headPageOffset = asset - > headPtr . offset ;
char * v8 = pak - > memoryData . patchDstPtr - asset - > headerSize ;
uint32_t newOffsetFromSegmentBufferToHeader = LODWORD ( pak - > memoryData . patchDstPtr )
- asset - > headerSize
- LODWORD ( a1 - > segmentBuffers [ 0 ] ) ;
asset - > headPtr . offset = newOffsetFromSegmentBufferToHeader ;
uint32_t offsetSize = newOffsetFromSegmentBufferToHeader - headPageOffset ;
for ( uint32_t i = pak - > memoryData . numShiftedPointers ; i < pak - > GetPointerCount ( ) ; pak - > memoryData . numShiftedPointers = i )
{
PakPage_t * ptr = & pak - > memoryData . virtualPointers [ i ] ;
ASSERT_PAKPTR_VALID ( pak , ptr ) ;
if ( ptr - > index ! = shiftedPageIndex )
break ;
const uint32_t offsetToPointer = ptr - > offset - headPageOffset ;
if ( offsetToPointer > = asset - > headerSize )
break ;
PakPage_t * pagePtr = reinterpret_cast < PakPage_t * > ( v8 + offsetToPointer ) ;
ASSERT_PAKPTR_VALID ( pak , ptr ) ;
ptr - > offset + = offsetSize ;
if ( pagePtr - > index = = shiftedPageIndex )
pagePtr - > offset + = offsetSize ;
i = pak - > memoryData . numShiftedPointers + 1 ;
}
for ( uint32_t j = 0 ; j < asset - > dependenciesCount ; + + j )
{
PakPage_t * descriptor = & pak - > memoryData . guidDescriptors [ asset - > dependenciesIndex + j ] ;
if ( descriptor - > index = = shiftedPageIndex )
descriptor - > offset + = offsetSize ;
}
const uint32_t v16 = + + pak - > memoryData . someAssetCount ;
PakAsset_t * v17 = nullptr ;
if ( v16 < pak - > GetAssetCount ( ) & & ( v17 = pak - > memoryData . ppAssetEntries [ v16 ] , v17 - > headPtr . index = = shiftedPageIndex ) )
{
pak - > memoryData . field_2A8 = v17 - > headPtr . offset - headPageOffset - asset - > headerSize ;
pak - > memoryData . patchSrcSize = v17 - > headerSize ;
const uint8_t assetTypeIdx = v17 - > HashTableIndexForAssetType ( ) ;
pak - > memoryData . patchDstPtr = reinterpret_cast < char * > ( a1 - > segmentBuffers [ 0 ] ) + pak - > memoryData . unkAssetTypeBindingSizes [ assetTypeIdx ] ;
pak - > memoryData . unkAssetTypeBindingSizes [ assetTypeIdx ] + = g_pPakGlobals - > m_assetBindings [ assetTypeIdx ] . nativeClassSize ;
}
else
{
bool res = SetupNextPageForPatching ( a1 , pak ) ;
if ( res )
continue ;
else
break ;
}
}
if ( ! JT_IsJobDone ( pak - > memoryData . unkJobID ) )
return false ;
uint32_t i = 0 ;
PakAsset_t * pAsset = nullptr ;
for ( int j = pak - > memoryData . pakId & PAK_MAX_HANDLES_MASK ; i < pak - > GetHeader ( ) . assetCount ; a1 - > assetGuids [ i - 1 ] = pAsset - > guid )
{
pAsset = & pak - > memoryData . assetEntries [ i ] ;
if ( pAsset - > numRemainingDependencies )
{
//printf("[%s] processing deps for %llX (%.4s)\n", pak->GetName(), pAsset->guid, (char*)&pAsset->magic);
Pak_ResolveAssetRelations ( pak , pAsset ) ;
const int v36 = pak - > memoryData . qword2E0 [ i ] ;
if ( dword_167A40B3C [ 6 * g_pPakGlobals - > m_assets [ v36 ] . unk_8 ] = = j )
{
if ( * qword_167ED7BC8 )
{
uint64_t v38 = 0 ;
if ( ( * qword_167ED7BC8 ) - > unk_0 )
{
int * v39 = ( * qword_167ED7BC8 ) - > unk_array_9D410 ;
while ( * v39 ! = v36 )
{
+ + v38 ;
+ + v39 ;
if ( v38 > = ( * qword_167ED7BC8 ) - > unk_0 )
goto LABEL_41 ;
}
goto LABEL_42 ;
}
}
else
{
//printf("allocating thing\n");
* qword_167ED7BC8 = reinterpret_cast < UnknownPakStruct_t * > ( AlignedMemAlloc ( ) - > Alloc ( 0x11D410 , 8 ) ) ;
( * qword_167ED7BC8 ) - > unk_0 = 0 ;
( * qword_167ED7BC8 ) - > unk_4 = 0 ;
( * qword_167ED7BC8 ) - > unk_8 = 0 ;
}
LABEL_41 :
( * qword_167ED7BC8 ) - > unk_array_9D410 [ ( * qword_167ED7BC8 ) - > unk_0 ] = v36 ;
+ + ( * qword_167ED7BC8 ) - > unk_0 ;
}
}
LABEL_42 :
+ + i ;
}
if ( * qword_167ED7BC8 )
sub_14043D870 ( a1 , 0 ) ;
a1 - > status = EPakStatus : : PAK_STATUS_LOADED ;
return true ;
}
void Pak_StubInvalidAssetBinds ( PakFile_t * const pak , PakSegmentDescriptor_t * const desc )
{
for ( uint32_t i = 0 ; i < pak - > GetAssetCount ( ) ; + + i )
{
PakAsset_t * const asset = & pak - > memoryData . assetEntries [ i ] ;
pak - > memoryData . ppAssetEntries [ i ] = asset ;
const uint8_t assetTypeIndex = asset - > HashTableIndexForAssetType ( ) ;
desc - > assetTypeCount [ assetTypeIndex ] + + ;
PakAssetBinding_t * const assetBinding = & g_pPakGlobals - > m_assetBindings [ assetTypeIndex ] ;
if ( assetBinding - > type = = PakAssetBinding_t : : NONE )
{
assetBinding - > extension = asset - > magic ;
assetBinding - > version = asset - > version ;
assetBinding - > description = " <unknown> " ;
assetBinding - > loadAssetFunc = nullptr ;
assetBinding - > unloadAssetFunc = nullptr ;
assetBinding - > replaceAssetFunc = nullptr ;
assetBinding - > allocator = AlignedMemAlloc ( ) ;
assetBinding - > headerSize = asset - > headerSize ;
assetBinding - > nativeClassSize = asset - > headerSize ;
assetBinding - > headerAlignment = pak - > memoryData . pageHeaders [ asset - > headPtr . index ] . pageAlignment ;
assetBinding - > type = PakAssetBinding_t : : STUB ;
}
// this is dev only because it could spam a lot on older paks
// which isn't much help to the average user that can't rebuild other people's paks
if ( asset - > version ! = assetBinding - > version )
{
DevWarning ( eDLL_T : : RTECH ,
" Unexpected asset version for \" %s \" (%.4s) asset with guid 0x%llX (asset %i in pakfile '%s'). Expected %i, found %i. \n " ,
assetBinding - > description ,
reinterpret_cast < char * > ( & asset - > magic ) ,
asset - > guid ,
i , pak - > GetName ( ) ,
assetBinding - > version , asset - > version
) ;
}
}
}
bool Pak_StartLoadingPak ( PakLoadedInfo_t * const loadedInfo )
{
PakFile_t * const pakFile = loadedInfo - > pakFile ;
if ( pakFile - > memoryData . patchSrcSize & & ! Pak_ProcessPakFile ( pakFile ) )
return false ;
PakSegmentDescriptor_t pakDescriptor = { } ;
Pak_StubInvalidAssetBinds ( pakFile , & pakDescriptor ) ;
const uint32_t numAssets = pakFile - > GetAssetCount ( ) ;
if ( pakFile - > memoryData . pakHeader . patchIndex )
pakFile - > firstPageIdx = pakFile - > memoryData . patchDataHeader - > m_pageCount ;
sub_140442740 ( pakFile - > memoryData . ppAssetEntries , & pakFile - > memoryData . ppAssetEntries [ numAssets ] , numAssets , pakFile ) ;
// pak must have no more than PAK_MAX_SEGMENTS segments as otherwise we will overrun the above "segmentSizes" array
// and write to arbitrary locations on the stack
if ( pakFile - > GetSegmentCount ( ) > PAK_MAX_SEGMENTS )
{
Error ( eDLL_T : : RTECH , EXIT_FAILURE , " Too many segments in pakfile '%s'. Max %i, found %i. \n " , pakFile - > GetName ( ) , PAK_MAX_SEGMENTS , pakFile - > GetSegmentCount ( ) ) ;
return false ;
}
Pak_AlignSegmentHeaders ( pakFile , & pakDescriptor ) ;
Pak_AlignSegments ( pakFile , & pakDescriptor ) ;
// allocate segment buffers with predetermined alignments; pages will be
// copied into here
for ( int8_t i = 0 ; i < PAK_SEGMENT_BUFFER_TYPES ; + + i )
{
if ( pakDescriptor . segmentSizeForType [ i ] )
loadedInfo - > segmentBuffers [ i ] = AlignedMemAlloc ( ) - > Alloc ( pakDescriptor . segmentSizeForType [ i ] , pakDescriptor . segmentAlignmentForType [ i ] ) ;
}
Pak_CopyPagesToSegments ( pakFile , loadedInfo , & pakDescriptor ) ;
const PakFileHeader_t & pakHdr = pakFile - > GetHeader ( ) ;
if ( * g_pUseAssetStreamingSystem )
{
Pak_LoadStreamingData ( loadedInfo ) ;
}
const __int64 v106 = pakHdr . descriptorCount + 2 * ( pakHdr . patchIndex + pakHdr . assetCount + 4ull * pakHdr . assetCount + pakHdr . virtualSegmentCount ) ;
const __int64 patchDestOffset = pakHdr . GetTotalHeaderSize ( ) + 2 * ( pakHdr . patchIndex + 6ull * pakHdr . memPageCount + 4 * v106 ) ;
pakFile - > dword14 = 1 ;
PakMemoryData_t & memoryData = pakFile - > memoryData ;
memoryData . patchSrcSize = pakFile - > memoryData . qword2D0 - patchDestOffset ;
memoryData . patchDstPtr = ( char * ) & pakHdr + patchDestOffset ;
loadedInfo - > status = EPakStatus : : PAK_STATUS_LOAD_PAKHDR ;
return true ;
}
void V_PakParse : : Detour ( const bool bAttach ) const
{
DetourSetup ( & v_Pak_LoadAsync , & Pak_LoadAsync , bAttach ) ;
DetourSetup ( & v_Pak_UnloadAsync , & Pak_UnloadAsync , bAttach ) ;
DetourSetup ( & v_Pak_StartLoadingPak , & Pak_StartLoadingPak , bAttach ) ;
DetourSetup ( & v_Pak_ProcessPakFile , & Pak_ProcessPakFile , bAttach ) ;
DetourSetup ( & v_Pak_ResolveAssetRelations , & Pak_ResolveAssetRelations , bAttach ) ;
DetourSetup ( & v_Pak_ProcessAssets , & Pak_ProcessAssets , bAttach ) ;
DetourSetup ( & sub_14043E030 , & Rebuild_14043E030 , bAttach ) ;
}
// Symbols taken from R2 dll's.
PakLoadFuncs_t * g_pakLoadApi = nullptr ;