RTech: reverse engineer and document most of pak load api

Most of the pak load functions are now reverse engineered, documented and ready to be used from the API handle. Structure is confirmed to align with the engine.
This commit is contained in:
Kawe Mazidjatari 2024-11-17 02:20:40 +01:00
parent 3eea52b199
commit 7a40db4d85

View File

@ -4,47 +4,155 @@
#include "tier0/jobthread.h"
#include "launcher/launcher.h"
#include "rtech/async/asyncio.h"
#include "rtech/ipakfile.h"
struct PakLoadFuncs_s
{
void* Initialize; // Returns the pak handle of the patch master RPak once initialized.
void* RegisterAsset;
char unknown0[8];
PakHandle_t(*LoadAsync)(const char* pakFileName, CAlignedMemAlloc* allocator, int nIdx, bool bUnk);
void* LoadAsyncAndWait;
void (*UnloadAsync)(PakHandle_t handle);
void* UnloadAsyncAndWait;
char unknown2[16];
void* Func7;
void* Func8;
PakStatus_e(*WaitAsync)(PakHandle_t handle, void* finishCallback);
void* Func10;
void* Func11;
void* FindByGUID;
void* FindByName;
char unknown3[8];
void* Func14;
void* Func15;
void* Func16;
void* Func17;
void* Func18;
void* IncrementStreamingAssetCount;
void* DecrementStreamingAssetCount;
void* IsFullStreamingInstall;
char unknown4[48];
int (*OpenAsyncFile)(const char* const fileName, int logLevel, size_t* const outFileSize);
void (*CloseAsyncFile)(short fileHandle);
// initializes the global states for RPak files and async reads.
// returns the pak handle of the patch master RPak once initialized.
// currently the system only knows 2 modes; 0 = asset streaming
// disabled, 1 = asset streaming enabled
PakHandle_t (*Initialize)(const int mode);
// register a specific asset with an unique fourcc identifier. the
// code will run the loadHandler when it encounters this asset in
// the pak file. when the asset is unloaded, the unload handler
// for this asset will be called. when a pak has been loaded that
// happens to contain an asset that was loaded in a prior pakfile,
// the patch handler for this asset type will be called which
// allows for patching the asset with the one from the new pak.
// - the class size should contain both the header size and the
// rest of the class itself
void (*const RegisterAsset)(const uint32 assetType, const uint32 assetVersion, const char* const assetTypeName,
const void* const loadHandler, const void* const unloadHandler, const void* const patchHandler,
CAlignedMemAlloc* const allocator, const uint32 headerSize, const uint32 classSize,
const uint32 alignment, const JobPriority_e jobPriority, const JobAffinity_t jobAffinity);
char unused0[8];
// load a pakfile asynchronously, returns the pakid on success,
// PAK_INVALID_HANDLE on failure
PakHandle_t(*const LoadAsync)(const char* const fileName, CAlignedMemAlloc* const allocator,
const int logChannel, bool bUnk);
// this method does the same as LoadAsync, however it will lock and wait
// until the requested pak has been loaded. during the lock and wait, the
// function will help with other pending or active load/unload jobs
PakHandle_t(*const LoadAsyncAndWait)(const char* const fileName, CAlignedMemAlloc* const allocator,
const int logChannel, void(*const finishCallback));
// unload a specific pakfile asynchronously by pakid
void (*UnloadAsync)(const PakHandle_t handle);
// this method does the same as UnloadAsync, however it will lock and wait
// until the requested pak has been unloaded. during the lock and wait, the
// function will help with other pending or active load/unload jobs
void (*UnloadAsyncAndWait)(const PakHandle_t handle);
char unused1[16];
// set the current thread sync function and returns the previously installed
// thread sync function
void* (*SetThreadSyncFunc)(void(* const callback));
// help with other allocated load/unload jobs
void (*HelpWithPendingRequests)();
// lock and wait for a specific pakfile to load by pakid, and help with other
// allocated jobs in the mean time
void (*WaitForAsyncLoad)(const PakHandle_t handle, void(* const finishCallback));
// lock and wait for a specific pakfile to unload by pakid, and help with other
// allocated jobs in the mean time
void (*WaitForAsyncUnload)(const PakHandle_t handle);
// get an exported function of a dynamic library attached to this pakfile.
// i.e. we have ui.rpak which has the flag PAK_HEADER_FLAGS_HAS_MODULE set,
// and has an associated ui.dll module loaded, from which we want to get
// the address of the export "rui_woman_face_02"
void* (*GetModuleFunction)(const PakHandle_t handle, const char* const procName);
// get the asset data pointer by asset guid
void* (*FindAssetByGUID)(const PakGuid_t guid);
// get the asset data pointer by asset name
void* (*FindAssetByName)(const char* const name);
char unused2[8];
// get the asset guid by asset data pointer
PakGuid_t (*FindGUIDByAsset)(const void* const asset);
void* Func15; // Unknown
void* Func16; // Unknown
// open either the mandatory or optional embedded streaming file
int (*OpenEmbeddedStreamingFile)(const PakHandle_t handle, const PakStreamSet_e set);
// checks if either the mandatory or optional streaming system is disabled
// for pakfile by streaming set; a pakfile could have it enabled for
// the mandatory streaming set while having it disabled for the optional set
bool (*IsStreamingDisabledForSet)(const PakHandle_t handle, const PakStreamSet_e set);
// atomically increment/decrement total streaming asset count shared across
// all loaded pakfiles
void (*IncrementStreamingAssetCount);
void (*DecrementStreamingAssetCount);
// returns whether the runtime has optional streaming assets loaded
bool (*HasOptionalStreamingAssetsLoaded)();
char unused3[48];
// open a specific file for asynchronous read, and return the file handle
int (*OpenAsyncFile)(const char* const fileName, const int logChannel, size_t* const outFileSize);
// close an opened file by its handle
void (*CloseAsyncFile)(const int fileHandle);
// atomically increments AsyncFileHandleTracker_s::state; some refcounting? see [r5apex.exe+438831h]
// for atomic exchange before unload. needs more reversing work
void* Func24;
// always set to nullptr
void* Func25;
void* ReadAsyncFile;
void* ReadAsyncFileWithUserData;
uint8_t(*CheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg);
uint8_t(*WaitAndCheckAsyncRequest)(int idx, size_t* const bytesProcessed, const char** const statusMsg);
void* WaitForAsyncFileRead;
void* Func31;
void* Func32;
void* Func33;
// asynchronously read an opened file by its handle, starting from specified
// offset until specified read size. the read data will be written into
// the provided read buffer. asynchronous reads are carved into chunks of
// PAK_READ_DATA_CHUNK_SIZE, to allow the system to cancel out at any point
// to create resources for more important tasks, e.g. we are trying to read
// a texture, but there is also a request for loading an audio sample from
// the banks, and audio has higher priority so cancel out
int (*ReadAsyncFile)(const int fileHandle, const size_t readOffset, const size_t readSize, void* const readBuffer, const int unk7);
// same as ReadAsyncFile, but takes 2 extra pointers, but the usage thereof has
// not been located. debug only?
int (*ReadAsyncFileWithUserData)(const int fileHandle, const size_t readOffset, const size_t readSize, const void* const readBuffer,
const void* const unk5, const void* const unk6, const int unk7);
// poll for the current async read status, see AsyncHandleStatus_s::Status_e
// for possible return statuses
AsyncHandleStatus_s::Status_e(*CheckAsyncRequest)(const int fileSlot, size_t* const bytesProcessed, const char** const statusMsg);
// same as CheckAsyncRequest, but locks and waits until the read has been
// finished. unlike other locking functions, this function does not help
// with other allocated jobs
AsyncHandleStatus_s::Status_e(*WaitAndCheckAsyncRequest)(const int fileSlot, size_t* const bytesProcessed, const char** const statusMsg);
// lock and waits until the read has been finished. unlike other locking
// functions, this function does not help with other allocated jobs
void (*WaitForAsyncRequest)(const int fileSlot);
// cancel an async read request and release the handle
void (*CancelAsyncRequestAndRelease)(const int fileSlot);
// cancel an async pak read request and release the handle
void (*CancelLoadRequest)(const int fileSlot);
// get the main async io worked thread
void (*GetAsyncIOWorkerThread)(HANDLE* const outThreadHandle);
};
inline PakGlobalState_s* g_pakGlobals;