RTech: fix numeric overflow caused by massive pak files

Pak files above 4GB caused the async file system to throw an error about failing to load audio banks, removed casts and promoted everything correctly. Also removed irrelevant comments in the public pakfile header.
This commit is contained in:
Kawe Mazidjatari 2024-01-28 21:43:03 +01:00
parent 52edcc6d84
commit 0452720cf8
4 changed files with 29 additions and 35 deletions

View File

@ -345,7 +345,7 @@ struct PakSegmentHeader_t
size_t dataSize; size_t dataSize;
}; };
struct PakSegmentDescriptor_t // TODO: give this a better name!!! struct PakSegmentDescriptor_t
{ {
size_t assetTypeCount[PAK_MAX_TYPES]; size_t assetTypeCount[PAK_MAX_TYPES];
int64_t segmentSizes[PAK_MAX_SEGMENTS]; int64_t segmentSizes[PAK_MAX_SEGMENTS];
@ -465,8 +465,8 @@ struct PakFileStream_t
_QWORD qword0; _QWORD qword0;
_QWORD qword8; _QWORD qword8;
int fileHandle; // TODO: Unsigned? int fileHandle;
int gap14[32]; // TODO: Unsigned? int gap14[32];
_BYTE gap94[32]; _BYTE gap94[32];
unsigned int unsigned_intB4; unsigned int unsigned_intB4;
_DWORD dwordB8; _DWORD dwordB8;
@ -476,7 +476,7 @@ struct PakFileStream_t
_BYTE byteBF; _BYTE byteBF;
Descriptor descriptors[PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS]; Descriptor descriptors[PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS];
uint8_t* buffer; uint8_t* buffer;
_QWORD qword1C8; _QWORD bufferMask;
_QWORD bytesStreamed; _QWORD bytesStreamed;
}; };
@ -567,6 +567,7 @@ struct PakMemoryData_t
const char* fileName; const char* fileName;
PakFileHeader_t pakHeader; PakFileHeader_t pakHeader;
PakPatchFileHeader_t patchHeader;
}; };
struct PakFile_t struct PakFile_t
@ -695,7 +696,7 @@ struct UnknownPakStruct_t
static_assert(sizeof(UnknownPakStruct_t) == 0x11D410); static_assert(sizeof(UnknownPakStruct_t) == 0x11D410);
static_assert(sizeof(PakFile_t) == 2208); // S3+ static_assert(sizeof(PakFile_t) == 2224); // S3+
static_assert(sizeof(PakLoadedInfo_t) == 184); static_assert(sizeof(PakLoadedInfo_t) == 184);
static_assert(sizeof(PakDecoder_t) == 136); static_assert(sizeof(PakDecoder_t) == 136);
static_assert(sizeof(PakPatchFileHeader_t) == 16); static_assert(sizeof(PakPatchFileHeader_t) == 16);

View File

@ -55,7 +55,7 @@ int FS_OpenAsyncFile(const char* const filePath, const int logLevel, size_t* con
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// close a file and remove it from the async file handle array // close a file and remove it from the async file handle array
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
void FS_CloseAsyncFile(const short fileHandle) void FS_CloseAsyncFile(const int fileHandle)
{ {
const int slotNum = fileHandle & ASYNC_MAX_FILE_HANDLES_MASK; const int slotNum = fileHandle & ASYNC_MAX_FILE_HANDLES_MASK;
AsyncHandleTracker_t& tracker = g_pAsyncFileSlots[slotNum]; AsyncHandleTracker_t& tracker = g_pAsyncFileSlots[slotNum];

View File

@ -48,10 +48,10 @@ struct AsyncHandleStatus_t
static_assert(sizeof(AsyncHandleStatus_t) == 0x40); static_assert(sizeof(AsyncHandleStatus_t) == 0x40);
extern int FS_OpenAsyncFile(const char* const filePath, const int logLevel, size_t* const fileSizeOut); extern int FS_OpenAsyncFile(const char* const filePath, const int logLevel, size_t* const fileSizeOut);
extern void FS_CloseAsyncFile(const short fileHandle); extern void FS_CloseAsyncFile(const int fileHandle);
inline int(*v_FS_OpenAsyncFile)(const char* const filePath, const int logLevel, size_t* const outFileSize); inline int(*v_FS_OpenAsyncFile)(const char* const filePath, const int logLevel, size_t* const outFileSize);
inline void(*v_FS_CloseAsyncFile)(short fileHandle); inline void(*v_FS_CloseAsyncFile)(const int fileHandle);
inline int(*v_FS_ReadAsyncFile)(int a1, __int64 a2, unsigned __int64 a3, void* a4, void* a5, void* a6, int a7); inline int(*v_FS_ReadAsyncFile)(int a1, __int64 a2, unsigned __int64 a3, void* a4, void* a5, void* a6, int a7);
inline uint8_t(*v_FS_CheckAsyncRequest)(AsyncHandleStatus_t* pakStatus, size_t* bytesProcessed, const char** stateString); inline uint8_t(*v_FS_CheckAsyncRequest)(AsyncHandleStatus_t* pakStatus, size_t* bytesProcessed, const char** stateString);

View File

@ -238,45 +238,39 @@ bool Pak_ProcessPakFile(PakFile_t* const pak)
PakFileStream_t* fileStream; // rsi PakFileStream_t* fileStream; // rsi
PakMemoryData_t* memoryData; // r14 PakMemoryData_t* memoryData; // r14
__int64 dwordB8; // rcx __int64 dwordB8; // rcx
unsigned int v6; // eax // [was: int] uint32_t v6; // eax
__int64 v7; // rax __int64 v7; // rax
char v8; // r13 char v8; // r13
//signed __int64 index_Maybe; // rdi uint64_t bytesProcessed; // r12
//char v10; // r15
//__int64 v11; // rdx
//const char* v12; // rbp
size_t bytesProcessed; // eax
char byteBF; // al
unsigned __int64 v16; // r9 unsigned __int64 v16; // r9
unsigned __int8 v17; // cl unsigned __int8 v17; // cl
unsigned __int64 v18; // r8 unsigned __int64 v18; // r8
uint8_t byte1F8; // al uint8_t byte1F8; // al
uint8_t byte1FD; // cl uint8_t byte1FD; // cl
PakFileStream_t::Descriptor* v22; // rdi PakFileStream_t::Descriptor* v22; // rdi
size_t dataOffset; // rax uint64_t dataOffset; // rax
PakDecoder_t* decodeContext; // rbp PakDecoder_t* decodeContext; // rbp
size_t decompressedSize; // rax uint64_t decompressedSize; // rax
size_t compressedSize; // rdx uint64_t compressedSize; // rdx
uint64_t qword1D0; // rcx uint64_t qword1D0; // rcx
__int64 v28; // rax __int64 v28; // rax
unsigned int numBitsRemaining; // r8d unsigned int numBitsRemaining; // r8d
int v35; // ecx int v35; // ecx
int v39; // r10d int v39; // r10d
int v40; // r9d int v40; // r9d
unsigned int v42; // ecx uint64_t v42; // ecx
unsigned int v43; // r8d unsigned int v43; // r8d
unsigned int v44; // r12d uint64_t v44; // r12d
char byteBC; // r15 char byteBC; // r15
__int64 v46; // rbp __int64 v46; // rbp
__int64 v47; // r8 __int64 v47; // r8
unsigned __int64 v48; // rbp unsigned __int64 v48; // rbp
unsigned __int64 qword8; // rax unsigned __int64 qword8; // rax
__int64 v50; // rdi __int64 patchCount; // rcx
char c; // al char c; // al
char* it; // rcx char* it; // rcx
char* i; // rdx char* i; // rdx
int v56; // edi int v56; // edi
unsigned int patchCount; // r15
unsigned __int64 v58; // rdx unsigned __int64 v58; // rdx
char pakPatchPath[MAX_PATH]; // [rsp+40h] [rbp-148h] BYREF char pakPatchPath[MAX_PATH]; // [rsp+40h] [rbp-148h] BYREF
unsigned __int64 v62; // [rsp+190h] [rbp+8h] unsigned __int64 v62; // [rsp+190h] [rbp+8h]
@ -292,7 +286,7 @@ bool Pak_ProcessPakFile(PakFile_t* const pak)
v62 = sizeof(PakFileHeader_t); v62 = sizeof(PakFileHeader_t);
v6 = fileStream->unsigned_intB4; v6 = fileStream->unsigned_intB4;
if (v6 != (_DWORD)dwordB8) if (v6 != dwordB8)
{ {
while (1) while (1)
{ {
@ -319,19 +313,17 @@ bool Pak_ProcessPakFile(PakFile_t* const pak)
fileStream->bytesStreamed += bytesProcessed; fileStream->bytesStreamed += bytesProcessed;
if (v8) if (v8)
{ {
byteBF = fileStream->byteBF++;
pakHeader = &pak->memoryData.pakHeader; pakHeader = &pak->memoryData.pakHeader;
v16 = (unsigned __int64)fileStream->unsigned_intB4 << 19; v16 = (unsigned __int64)fileStream->unsigned_intB4 << 19;
v17 = fileStream->byteBF++ & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK;
if (v8 == 2) if (v8 == 2)
{ {
v18 = v16 & fileStream->qword1C8; v18 = v16 & fileStream->bufferMask;
fileStream->bytesStreamed = bytesProcessed + v16; fileStream->bytesStreamed = bytesProcessed + v16;
pakHeader = (PakFileHeader_t*)&fileStream->buffer[v18]; pakHeader = (PakFileHeader_t*)&fileStream->buffer[v18];
} }
v17 = byteBF & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK;
fileStream->descriptors[v17].dataOffset = v16 + sizeof(PakFileHeader_t); fileStream->descriptors[v17].dataOffset = v16 + sizeof(PakFileHeader_t);
fileStream->descriptors[v17].compressedSize = v16 + pakHeader->compressedSize; fileStream->descriptors[v17].compressedSize = v16 + pakHeader->compressedSize;
fileStream->descriptors[v17].decompressedSize = pakHeader->decompressedSize; fileStream->descriptors[v17].decompressedSize = pakHeader->decompressedSize;
@ -343,9 +335,9 @@ LABEL_18:
byte1F8 = pak->byte1F8; byte1F8 = pak->byte1F8;
if (byte1F8 != fileStream->byteBF) if (byte1F8 != fileStream->byteBF)
{ {
byte1FD = pak->byte1FD;
const bool useZStream = pak->GetHeader().flags & PAK_HEADER_FLAGS_ZSTREAM; const bool useZStream = pak->GetHeader().flags & PAK_HEADER_FLAGS_ZSTREAM;
byte1FD = pak->byte1FD;
do do
{ {
v22 = &fileStream->descriptors[byte1F8 & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK]; v22 = &fileStream->descriptors[byte1F8 & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK];
@ -384,7 +376,7 @@ LABEL_18:
decompressedSize = Pak_InitDecoder(&pak->pakDecoder, decompressedSize = Pak_InitDecoder(&pak->pakDecoder,
fileStream->buffer, pak->decompBuffer, fileStream->buffer, pak->decompBuffer,
PAK_DECODE_IN_RING_BUFFER_MASK, PAK_DECODE_OUT_RING_BUFFER_MASK, PAK_DECODE_IN_RING_BUFFER_MASK, PAK_DECODE_OUT_RING_BUFFER_MASK,
v22->compressedSize - (v22->dataOffset - sizeof(PakFileHeader_t)), v22->compressedSize - (v22->dataOffset - sizeof(PakFileHeader_t)),
v22->dataOffset - sizeof(PakFileHeader_t), sizeof(PakFileHeader_t), useZStream); v22->dataOffset - sizeof(PakFileHeader_t), sizeof(PakFileHeader_t), useZStream);
@ -493,7 +485,7 @@ LABEL_45:
v43 = fileStream->dwordB8; v43 = fileStream->dwordB8;
if ((unsigned int)(pak->inputBytePos >> 19) < v42) if ((unsigned int)(pak->inputBytePos >> 19) < v42)
v42 = (unsigned int)pak->inputBytePos >> 19; // New cast added v42 = pak->inputBytePos >> 19;
v44 = v42 + 32; v44 = v42 + 32;
@ -512,18 +504,19 @@ LABEL_45:
qword8 = fileStream->qword8; qword8 = fileStream->qword8;
if (v62 < qword8) if (v62 < qword8)
{ {
v50 = (unsigned int)v47;
if (v48 < qword8) if (v48 < qword8)
qword8 = v48; qword8 = v48;
fileStream->gap14[(unsigned int)v47] = v_FS_ReadAsyncFile(
fileStream->gap14[v47] = v_FS_ReadAsyncFile(
fileStream->fileHandle, fileStream->fileHandle,
v62 - fileStream->qword0, v62 - fileStream->qword0,
qword8 - v62, qword8 - v62,
&fileStream->buffer[v62 & fileStream->qword1C8], &fileStream->buffer[v62 & fileStream->bufferMask],
0i64, 0i64,
0i64, 0i64,
4); 4);
fileStream->gap94[v50] = byteBC;
fileStream->gap94[v47] = byteBC;
fileStream->byteBC = 0; fileStream->byteBC = 0;
goto LABEL_65; goto LABEL_65;
} }
@ -595,7 +588,7 @@ LABEL_45:
fileStream->gap14[v47] = -2; fileStream->gap14[v47] = -2;
fileStream->gap94[v47] = 1; fileStream->gap94[v47] = 1;
if ((((_BYTE)v47 + 1) & PAK_MAX_ASYNC_STREAMED_LOAD_REQUESTS_MASK) == 0) if ((((_BYTE)v47 + 1) & 7) == 0)
fileStream->byteBC = 2; fileStream->byteBC = 2;
LABEL_65: LABEL_65: