|
6 | 6 | #include <Logger.h> |
7 | 7 | #include "GwDatTextureModule.h" |
8 | 8 |
|
| 9 | +#include <GWCA/Managers/GameThreadMgr.h> |
| 10 | +#include <GWCA/Utilities/Scanner.h> |
| 11 | + |
9 | 12 | #include "Resources.h" |
10 | 13 | #include <Utils/ArenaNetFileParser.h> |
11 | 14 | #include <Utils/GwDat/GwDatArchive.h> |
|
15 | 18 |
|
16 | 19 | namespace { |
17 | 20 |
|
| 21 | + // Game file-request trigger: asks the client to load a file id from its dat/network (the safe |
| 22 | + // FUN_0082da30 variant, which no-ops on bad state). Byte-pattern scanned against build 388118, so |
| 23 | + // it may need re-deriving after a client update; if it doesn't resolve, async reads just wait |
| 24 | + // passively for the client to stream the file on its own. |
| 25 | + using RequestFiles_pt = void(__cdecl*)(uint32_t count, const uint32_t* file_ids, uint32_t flags); |
| 26 | + constexpr uint32_t kTriggerFlags = 0x2; // enqueue + kick the download pump |
| 27 | + RequestFiles_pt RequestFiles_Func = nullptr; |
| 28 | + |
| 29 | + void WireGameFileTrigger() |
| 30 | + { |
| 31 | + RequestFiles_Func = reinterpret_cast<RequestFiles_pt>(GW::Scanner::Find( |
| 32 | + "\x55\x8b\xec\x53\x8b\x5d\x08\x56\x57\x85\xdb\x0f\x84\x9c\x02\x00\x00" |
| 33 | + "\x83\x3d\x78\x52\x07\x01\x00\x0f\x85\x8f\x02\x00\x00\x8b\x35\xf4\x76\xbe\x00\x85\xf6", |
| 34 | + "xxxxxxxxxxxxx????xx????xxx????xx????xx", 0)); |
| 35 | + if (!RequestFiles_Func) { |
| 36 | + Log::Log("[GwDat] game file-request trigger not found; async reads will wait passively."); |
| 37 | + return; |
| 38 | + } |
| 39 | + Log::Log("[GwDat] game file-request trigger resolved at %p", reinterpret_cast<void*>(RequestFiles_Func)); |
| 40 | + GwDatArchive::Instance().SetTrigger([](uint32_t file_id) { |
| 41 | + // FUN_0082da30 touches client state, so issue the request on the game thread. |
| 42 | + GW::GameThread::Enqueue([file_id] { |
| 43 | + if (RequestFiles_Func) |
| 44 | + RequestFiles_Func(1, &file_id, kTriggerFlags); |
| 45 | + }); |
| 46 | + }); |
| 47 | + } |
| 48 | + |
18 | 49 | struct Vec2i { |
19 | 50 | int x = 0; |
20 | 51 | int y = 0; |
@@ -320,6 +351,8 @@ void GwDatTextureModule::Initialize() |
320 | 351 | ToolboxModule::Initialize(); |
321 | 352 | // The dat is indexed lazily on the first read; start its dedicated read/decode worker. |
322 | 353 | GwDatArchive::Instance().StartWorker(); |
| 354 | + // Let async reads prompt the client to fetch a streamed-only file (best-effort; see the helper). |
| 355 | + WireGameFileTrigger(); |
323 | 356 | } |
324 | 357 |
|
325 | 358 | IDirect3DTexture9** GwDatTextureModule::LoadTextureFromFileId(uint32_t file_id, uint32_t stream_id) |
|
0 commit comments