Skip to content

Commit 76758db

Browse files
committed
Merge branch 'fix/dat-thread-hang' into dev
Kept the file_known root-cause fix from fix/dat-thread-hang (only warn when the file itself is genuinely absent, not merely missing a speculatively-probed stream) combined with dev's own diagnostic addition of file_id to the warning message.
2 parents 6893c06 + 2418741 commit 76758db

2 files changed

Lines changed: 19 additions & 15 deletions

File tree

GWToolboxdll/Modules/GwDatModule.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,14 @@ bool GwDatModule::ParseIndex()
583583
}
584584

585585
// Copies the raw (still-compressed) bytes for file_id/stream_id. The index is immutable after EnsureLoaded().
586-
bool GwDatModule::ReadRaw(uint32_t file_id, uint32_t stream_id, std::vector<uint8_t>& input, bool& compressed)
586+
// file_known is set true once file_id itself is found, so callers can tell "no such file" apart from "file exists, just not this stream".
587+
bool GwDatModule::ReadRaw(uint32_t file_id, uint32_t stream_id, std::vector<uint8_t>& input, bool& compressed, bool& file_known)
587588
{
589+
file_known = false;
588590
const auto found = m_fileid_to_slot.find(file_id);
589591
if (found == m_fileid_to_slot.end())
590592
return false;
593+
file_known = true;
591594
// A file's streams are a linked list: `c` is the stream number, `id` the next stream's slot.
592595
int idx = found->second;
593596
const MftEntry* e = nullptr;
@@ -636,19 +639,20 @@ bool GwDatModule::ReadFile(uint32_t file_id, std::vector<uint8_t>& out, uint32_t
636639

637640
std::vector<uint8_t> input;
638641
bool compressed = false;
639-
if (!self.ReadRaw(file_id, stream_id, input, compressed)) {
640-
// The dat is mapped but doesn't contain this file - almost always an incomplete Steam/streaming
641-
// install. Flag it (the UI surfaces this) and point the user at -image once.
642-
self.m_missing_data.store(true, std::memory_order_relaxed);
643-
static std::once_flag warned;
644-
std::call_once(warned, [file_id] {
645-
Log::Warning("GWToolbox couldn't find some image data in your Gw.dat - your local game data looks "
646-
"incomplete (Steam downloads it on demand). Run Guild Wars once with the -image "
647-
"command-line option to download all game data, then restart. file_id %d. Setup steps: "
648-
"https://gwtoolbox.com/docs/troubleshooting/#missing-images-in-toolbox",
649-
file_id
650-
);
651-
});
642+
bool file_known = false;
643+
if (!self.ReadRaw(file_id, stream_id, input, compressed, file_known)) {
644+
if (!file_known) {
645+
// The dat doesn't have this file at all - likely an incomplete Steam/streaming install; a missing stream on a file that does exist doesn't count (routine - several icon streams are speculatively probed).
646+
self.m_missing_data.store(true, std::memory_order_relaxed);
647+
static std::once_flag warned;
648+
std::call_once(warned, [file_id] {
649+
Log::Warning("GWToolbox couldn't find some image data in your Gw.dat - your local game data looks "
650+
"incomplete (Steam downloads it on demand). Run Guild Wars once with the -image "
651+
"command-line option to download all game data, then restart. file_id %d. Setup steps: "
652+
"https://gwtoolbox.com/docs/troubleshooting/#missing-images-in-toolbox",
653+
file_id);
654+
});
655+
}
652656
return false;
653657
}
654658

GWToolboxdll/Modules/GwDatModule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class GwDatModule : public ToolboxModule {
9393
bool AcquireMappingInto(void*& mapping, long long& size);
9494
bool ParseFrom(void* mapping, long long size, std::vector<MftEntry>& slots,
9595
std::unordered_map<uint32_t, int>& fileid_to_slot); // header + MFT + hash list -> temporaries
96-
bool ReadRaw(uint32_t file_id, uint32_t stream_id, std::vector<uint8_t>& input, bool& compressed);
96+
bool ReadRaw(uint32_t file_id, uint32_t stream_id, std::vector<uint8_t>& input, bool& compressed, bool& file_known);
9797

9898
std::mutex m_load_mutex; // serialises the one-time ParseIndex
9999
std::atomic<bool> m_loaded{false};

0 commit comments

Comments
 (0)