r5sdk/r5dev/rtech/async/asyncio.h
Kawe Mazidjatari f5a8ca3e7a 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.
2024-04-05 17:56:49 +02:00

105 lines
3.7 KiB
C++

#ifndef RTECH_ASYNCIO_H
#define RTECH_ASYNCIO_H
#include "rtech/iasync.h"
#include "rtech/rstdlib.h"
struct AsyncHandleTracker_t
{
int m_nFileNumber;
int m_nCurOfs;
HANDLE m_hFileHandle;
};
struct AsyncHandleStatus_t
{
enum EStatus : uint8_t
{
// the file is still pending, or being read at this moment
FS_ASYNC_PENDING = 0,
// the file is ready to be used
FS_ASYNC_READY,
// there was an error while reading the file
FS_ASYNC_ERROR,
// async read operations were canceled
FS_ASYNC_CANCELLED
};
int slot;
int unk2;
int unk3;
int unk4;
__int64 unk5;
// pointer to user defined data
void* userData;
void* unkFunctionPointer;
void* unkStatusPointer;
int unk6;
int unkFlag0;
__int16 unkFlag2;
__int16 unkFlag3;
__int16 unk8;
EStatus readStatus;
};
static_assert(sizeof(AsyncHandleStatus_t) == 0x40);
extern int FS_OpenAsyncFile(const char* const filePath, const int logLevel, size_t* const fileSizeOut);
extern void FS_CloseAsyncFile(const int fileHandle);
inline int(*v_FS_OpenAsyncFile)(const char* const filePath, const int logLevel, size_t* const outFileSize);
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 uint8_t(*v_FS_CheckAsyncRequest)(AsyncHandleStatus_t* pakStatus, size_t* bytesProcessed, const char** stateString);
inline AsyncHandleTracker_t* g_pAsyncFileSlots; // bufSize=1024*sizeof(FileHandleTracker_t).
inline RHashMap_MT* g_pAsyncFileSlotMgr; // Manages 'g_pakFileSlots'.
inline AsyncHandleStatus_t* g_pAsyncStatusSlots; // bufSize=256*sizeof(PakStatus_t).
inline RHashMap_MT* g_pAsyncStatusSlotMgr; // Manages 'g_pakStatusSlots'.
class V_AsyncIO : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("FS_OpenAsyncFile", v_FS_OpenAsyncFile);
LogFunAdr("FS_CloseAsyncFile", v_FS_CloseAsyncFile);
LogFunAdr("FS_ReadAsyncFile", v_FS_ReadAsyncFile);
LogFunAdr("FS_CheckAsyncRequest", v_FS_CheckAsyncRequest);
LogVarAdr("g_asyncFileSlots", g_pAsyncFileSlots);
LogVarAdr("g_asyncFileSlotMgr", g_pAsyncFileSlotMgr);
LogVarAdr("g_asyncStatusSlots", g_pAsyncStatusSlots);
LogVarAdr("g_asyncStatusSlotMgr", g_pAsyncStatusSlotMgr);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 89 85 08 01 ?? ??").FollowNearCallSelf().GetPtr(v_FS_OpenAsyncFile);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B D9 48 8D 35 ?? ?? ?? ??").GetPtr(v_FS_CloseAsyncFile);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 4C 89 64 24 ?? 41 55 41 56 41 57 48 83 EC 20 8B C1").GetPtr(v_FS_ReadAsyncFile);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 20 0F B6 79").GetPtr(v_FS_CheckAsyncRequest);
}
virtual void GetVar(void) const
{
extern void(*v_StreamDB_Init)(const char* const pszLevelName);
const CMemory streamDbBase(v_StreamDB_Init);
g_pAsyncFileSlots = streamDbBase.Offset(0x70).FindPatternSelf("4C 8D", CMemory::Direction::DOWN, 512, 1).ResolveRelativeAddress(0x3, 0x7).RCast<AsyncHandleTracker_t*>();
g_pAsyncFileSlotMgr = streamDbBase.Offset(0x70).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 512, 2).ResolveRelativeAddress(0x3, 0x7).RCast<RHashMap_MT*>();
g_pAsyncStatusSlots = g_GameDll.FindPatternSIMD("0F B6 C9 48 8D 05 ?? ?? ?? ??").FindPatternSelf("48 8D 05").ResolveRelativeAddress(0x3, 0x7).RCast<AsyncHandleStatus_t*>();
g_pAsyncStatusSlotMgr = streamDbBase.Offset(0x190).FindPatternSelf("48 8D 0D", CMemory::Direction::DOWN, 512, 2).ResolveRelativeAddress(0x3, 0x7).RCast<RHashMap_MT*>();
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const;
};
#endif // !ASYNCIO_H